diff --git a/packages/neo-one-client-core/src/Client.ts b/packages/neo-one-client-core/src/Client.ts index fb2147a3e3..e0f917d6e4 100644 --- a/packages/neo-one-client-core/src/Client.ts +++ b/packages/neo-one-client-core/src/Client.ts @@ -132,7 +132,7 @@ export class Client< // tslint:disable-next-line no-any TUserAccountProvider extends UserAccountProvider = any, // tslint:disable-next-line no-any - TUserAccountProviders extends UserAccountProviders = any + TUserAccountProviders extends UserAccountProviders = any, > { /** * Hook into the lifecycle of various requests. Can be used to automatically add logging, or parameter transformations across the application, for example. @@ -640,9 +640,7 @@ export class Client< }); } - protected getTransfersOptions( - argsIn: readonly any[], - ): { + protected getTransfersOptions(argsIn: readonly any[]): { readonly transfers: readonly Transfer[]; readonly options: TransactionOptions; } { diff --git a/packages/neo-one-client-core/src/sc/createSmartContract.ts b/packages/neo-one-client-core/src/sc/createSmartContract.ts index 2498eb04c1..5be0eb37f4 100644 --- a/packages/neo-one-client-core/src/sc/createSmartContract.ts +++ b/packages/neo-one-client-core/src/sc/createSmartContract.ts @@ -398,6 +398,7 @@ export const createSmartContract = ({ }), { client, + // TODO: need to add documentation back to the website for these when added back // iterEvents, // iterLogs, // iterActions, diff --git a/packages/neo-one-smart-contract/src/index.d.ts b/packages/neo-one-smart-contract/src/index.d.ts index 0ad62cf450..78717f7ec3 100644 --- a/packages/neo-one-smart-contract/src/index.d.ts +++ b/packages/neo-one-smart-contract/src/index.d.ts @@ -296,7 +296,7 @@ export interface Transaction { */ readonly height: number; /** - * Code that was executed in NEO VM. + * Code that was executed in the NeoVM. */ readonly script: Buffer; /** diff --git a/packages/neo-one-website/docs-old/0-installation/0-getting-started.md b/packages/neo-one-website/docs-old/0-installation/0-getting-started.md deleted file mode 100644 index aeed1587a2..0000000000 --- a/packages/neo-one-website/docs-old/0-installation/0-getting-started.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -slug: getting-started -title: Getting Started ---- - -This page is an overview of the NEO•ONE documentation and related resources. - -**NEO•ONE** makes coding, testing and deploying NEO dapps easy, fast, efficient and enjoyable. - ---- - -[[toc]] - ---- - -## Try NEO•ONE - -NEO•ONE has been designed as a full end-to-end toolkit for building NEO dapps. From developing a smart contract, to testing, to interacting with it from your front-end, the entire dapp lifecycle is covered with NEO•ONE. However, it's not necessary to use NEO•ONE for every part of your dapp, you can pick and choose the parts of NEO•ONE that make sense for your development. - -The links in this section will help you get started. - -### Courses - -If you're interested in playing around with NEO•ONE or you prefer to **learn by doing**, check out [NEO•ONE Courses](/course). As you work through the first two lessons you'll experience the entire development lifecycle of a dapp by deploying a fully functioning ICO, from the smart contract that powers it all to the UI that enables participation. All directly from your browser - no environment setup required. - -### Tutorial - -If you'd prefer to use your own editor, you can work through the [NEO•ONE Tutorial](/tutorial). The tutorial covers roughly the same content as the first course and by the end of it you'll be ready to start building your own unique dapp. - -### Playground - -Setup the [NEO•ONE Playground](/docs/playground) repository to get a feel for NEO•ONE in a real-world setting. Try modifying the smart contracts, adding to the tests or playing with the UI. Once you're comfortable, you can even try adding your own dapp! - ---- - -## Learn NEO•ONE - -NEO•ONE covers the entire development lifecycle of a dapp, so it's best to learn it one step at a time. - -### First Examples - -The [NEO•ONE Homepage](/) contains a full editor with a simplified token smart contract example and tests. Even if you don't know anything about building dapps, check it out to see what's possible. - -### TypeScript Resources - -NEO•ONE is written in TypeScript and the documentation assumes some familiarity with TypeScript. If you've never used TypeScript before, or it's been a while, keep the [TypeScript documentation](https://www.typescriptlang.org/docs/handbook/basic-types.html) handy while working through the NEO•ONE documentation. - -Prefer JavaScript or don't want to use TypeScript? No problem! NEO•ONE smart contracts are the only part of the framework that requires coding in TypeScript, otherwise you're free to use either JavaScript or TypeScript. - -### Blockchain Resources - -The majority of the documentation assumes general familiarity with blockchain and the NEO blockchain in particular. Check out the [Blockchain Basics](/docs/blockchain-basics) chapter of the main guide if you are unfamiliar with the general blockchain concepts or need a refresher. - -### Step-by-Step Guide - -If you'd prefer to just get an overview of NEO•ONE and learn about the core concepts, check out the [guide to main concepts](/docs/hello-world). Every chapter builds on the knowledge introduced in previous chapters so you won't miss a thing. - -### Advanced Guides - -Once you're comfortable with the main concepts and have built some simple dapps with NEO•ONE, you might be interested in some of the more advanced features NEO•ONE has to offer. The advanced guides section will introduce you to some less commonly used, but powerful, features. - -### API Reference - -This documentation section is useful for learning about specific details of the NEO•ONE API. For example, the [@neo-one/smart-contract API reference](/reference/@neo-one/smart-contract) can provide details on the APIs available for smart contracts. - ---- - -## Staying Informed - -The [NEO•ONE blog](/blog) is the official source of updates from the NEO•ONE team. Here you will find things like release notes and deprecation notices. - -Additionally, you can get the same updates by following [@neo-one-suite](https://twitter.com/neo_one_suite) on Twitter. - -Finally, feel free to chat with us directly on the [NEO•ONE Discord](https://discord.gg/S86PqDE). - ---- - -## Help - -Need help? NEO•ONE is developed by community members just like you. Contributors are often around and available for questions. First, see if you can find what you're looking for in the docs. If you can't find the answer, come chat with us in the [#support](https://discord.gg/S86PqDE) channel in the NEO•ONE Discord community. Many members of the community also use Stack Overflow. Read through [existing questions](https://stackoverflow.com/questions/tagged/neo-one) tagged with **neo-one** or [ask your own](https://stackoverflow.com/questions/ask)! - ---- - -## Something Missing? - -If something is missing from the NEO•ONE documentation or you found something confusing, please submit an issue to the [NEO•ONE GitHub](https://github.com/neo-one-suite/neo-one) with your suggestions. You can also tweet [@neo-one-suite](https://twitter.com/neo_one_suite) or let us know directly on the [NEO•ONE Discord](https://discord.gg/S86PqDE). We'd love to hear from you! diff --git a/packages/neo-one-website/docs-old/0-installation/1-environment-setup.md b/packages/neo-one-website/docs-old/0-installation/1-environment-setup.md deleted file mode 100644 index 348c03e327..0000000000 --- a/packages/neo-one-website/docs-old/0-installation/1-environment-setup.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -slug: environment-setup -title: Environment Setup ---- - -NEO•ONE was designed to get your dapp up and running quickly. - -This page describes how to setup NEO•ONE using `yarn` or `npm`. - ---- - -[[toc]] - ---- - -## Requirements - -- [Node](https://nodejs.org) >= 10.16.0 (We recommend the latest version) - - Linux and Mac: We recommend using [Node Version Manager](https://github.com/creationix/nvm). - - Windows: We recommend using [Chocolatey](https://chocolatey.org/). - ---- - -## Installation - -**If you're just getting started**, try out one of the following toolchains for setting up your project: - -- [Create React App](https://github.com/facebook/create-react-app) - Generates a [React](https://reactjs.org/) starter app. -- [Angular CLI](https://cli.angular.io/) - Generates an [Angular](https://angular.io/) starter app. -- [Vue CLI](https://cli.vuejs.org/) - Generate a [Vue](https://vuejs.org/) starter app. - -**Once you have a project setup**, the next step is to add NEO•ONE to it. NEO•ONE is organized into multiple individual packages. Use as much or as little as you like. Each package may be installed using either [yarn](https://yarnpkg.com/) (`yarn add `) or [npm](https://www.npmjs.com/) (`npm install `). Each package has the form `@neo-one/`, for example, `@neo-one/client`. - -Make sure to install the correct versions of these packages. If you are working on Neo2 then make sure you are installing NEO•ONE packages at version 2.x.x or lower. Version 3.0.0 or higher will be for Neo3. - -Install all the neo-one packages with yarn by running: - -```bash -yarn add @neo-one/client @neo-one/cli @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin -``` - -Install everything individually with npm by running: - -```bash -npm install @neo-one/client @neo-one/cli @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin -``` - -and then follow the [main guide](/docs/hello-world) or the [tutorial](/tutorial). By the end of it you'll know which features of NEO•ONE you're using and which packages to keep. - -Know what you want to use from NEO•ONE? Read on to see which packages to install for specific functionality. - -For interacting with smart contracts, you should install - -- `@neo-one/client` - Main entrypoint to the most common NEO•ONE client APIs. - -For local network and smart contract management, you should install - -- `@neo-one/cli` - Provides the `neo-one` cli command which manages common tasks like building and deploying smart contracts and spinning up local networks. - -In addition to the above, if you're developing TypeScript smart contracts using NEO•ONE, you should install - -- `@neo-one/smart-contract` - TypeScript smart contract standard library. -- `@neo-one/smart-contract-test` - TypeScript smart contract testing utilitiees. -- `@neo-one/smart-contract-lib` - Template library for common smart contract patterns. -- `@neo-one/smart-contract-typescript-plugin` - TypeScript language server plugin for inline compiler diagnostics in your favorite IDE. - -### Update - -```bash -#npm update @neo-one/cli -yarn upgrade @neo-one/cli -``` - -### Editor Setup - -Configure your IDE to use your local TypeScript installation and the `@neo-one/smart-contract-typescript-plugin` in order to take advantage of inline compiler diagnostics. These instructions are for [VSCode](https://code.visualstudio.com/), but they should be similar for any editor that supports TypeScript IntelliSense. - -1. Ensure `@neo-one/cli` and `@neo-one/smart-contract-typescript-plugin` are installed. -2. Run `yarn neo-one init` or `npx neo-one init`. This will create a `tsconfig.json` file in the configured smart contract directory (by default, `neo-one/contracts/tsconfig.json`). -3. Open a TypeScript file, then click the TypeScript version number in the lower right hand side of your editor and choose "Use Workspace Version" - -That's it! Enjoy inline smart contract compiler diagnostics. - -## Javascript Environment Requirements - -NEO•ONE depends on several types which older browser may not support. NEO•ONE requires the collection types [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) as well as [Symbol.asyncIterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator). If you support older browsers and devices which may not yet provide these natively, consider including a global polyfill in your bundled application, such as [core-js](https://github.com/zloirock/core-js) or [babel-polyfill](https://babeljs.io/docs/en/babel-polyfill/). - -To polyfill an environment for NEO•ONE using core-js, include the following lines at the top of your entry point. - -```typescript -import 'core-js/es/map'; -import 'core-js/es/set'; -import 'core-js/es/symbol/async-iterator'; -``` diff --git a/packages/neo-one-website/docs-old/0-installation/2-cli.md b/packages/neo-one-website/docs-old/0-installation/2-cli.md deleted file mode 100644 index 3964d654ca..0000000000 --- a/packages/neo-one-website/docs-old/0-installation/2-cli.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -slug: cli -title: CLI ---- - -The NEO•ONE CLI is your entry point for all of NEO•ONE's functionality. - -Run `yarn neo-one --help` to see the CLI commands available and their descriptions. -Run `yarn neo-one --help` to see what arguments are available for that command. -Run `yarn neo-one --version` to get the version of NEO•ONE that you are running. - -The NEO•ONE CLI will look for a configuration file named `.neo-one.config.ts` or `.neo-one.config.js`. If you need to provide a path to your configuration file for whatever reason you can provide an optional `--configPath ` argument to any of these CLI commands, which will tell NEO•ONE where to find your config file for that command. The path must be exact and must end with the exact file name. This option should not be needed. - ---- - -[[toc]] - ---- - -## neo-one init - -Initializes a new project in the current directory. This will create a default `.neo-one.config.ts` configuration file, -a sample `Hello World` smart contract in `neo-one/contracts/HelloWorld.ts`, and a unit test in -`src/__tests__/HelloWorld.ts`. - -| Argument | Type | Default | Description | -| -------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------- | -| `--react` | `boolean` | `false` | Setting this to true will generate an example. React component that uses the `HelloWorld` smart contract | -| `--typescript` | `boolean` | `false` | Setting this to true will initialize a TypeScript NEO•ONE project including generating a default `tsconfig.json` file | - ---- - -## neo-one build - -Builds the project and deploys it to the local development network based on the configuration found in the -NEO•ONE config file. - -| Argument | Type | Default | Description | -| --------- | --------- | ------- | ------------------------------------------------- | -| `--reset` | `boolean` | `false` | Setting this to true will reset the local project | - ---- - -## neo-one generate - -Compiles the smart contracts and generates the code helpers. This is a portion of what the `neo-one build` command does without starting a private network and deploying the contracts. - ---- - -## neo-one new - -Create new resources. `neo-one new private-key` is the only available option for now, which will generate a -new private key. - ---- - -## neo-one start - -Start NEO•ONE services. This command takes one argument after the command (`neo-one start `) which -can be either `network` or `neotracker`. `neo-one start network` will start the local development network. -`neo-one start neotracker` will start the local NEO Tracker instance. - ---- - -## neo-one stop - -Stop NEO•ONE services. This command takes one argument after the command (`neo-one stop `) which -can be either `network` or `neotracker`. `neo-one stop network` will stop the local development network. -`neo-one stop neotracker` will stop the local NEO Tracker instance. - ---- - -## neo-one deploy - -Deploys the project using the migration file. - -| Argument | Type | Default | Description | -| ----------- | -------- | -------- | ------------------------------- | -| `--network` | `string` | `"test"` | Network to run the migration on | - ---- - -## neo-one info - -Prints the project configuration. - ---- - -## neo-one compile - -Compiles a project's smart contracts and outputs the code to a local directory. You can set the arguments for this command -either in the NEO•ONE config file (ie. `.neo-one.config.ts`) or as a CLI argument. A CLI argument will override what is found in the config file. If an argument is not defined as a CLI argument and is not defined in the config file then the below defaults will be used. - -| Argument | Type | Default | Description | -| ----------- | --------- | ------------------- | ---------------------------------------------------------------------------- | -| `--outDir` | `string` | `neo-one/compiled` | Directory to output the compiled code | -| `--path` | `string` | `neo-one/contracts` | Path to the smart contract directory | -| `--json` | `boolean` | `true` | Output the contract with the JSON format | -| `--avm` | `boolean` | `false` | Output the contract with the AVM format | -| `--debug` | `boolean` | `false` | Output additional debug information | -| `--opcodes` | `boolean` | `false` | Output the AVM in a human-readable format for debugging (requires `--debug`) | - ---- - -## neo-one convert - -Converts values from one type to another. - -This command takes two arguments after the command (`neo-one convert `) which -can be either `address`, `private-key`, `public-key`, `script-hash`, or `wif` and then the input value. This will convert the input value from the designated input type to various output formats and prints them to stdout. For example `neo-one convert private-key ` will print the private key, WIF, address, public key, and script hash for that private key. - ---- - -## neo-one console - -Starts a REPL with project contracts and NEO•ONE Client APIs. - -| Argument | Type | Default | Description | -| ------------ | ------- | ----------- | ----------------------------------------------- | -| `--networks` | `array` | `["local"]` | Networks to initialize before starting the REPL | diff --git a/packages/neo-one-website/docs-old/0-installation/3-playground.md b/packages/neo-one-website/docs-old/0-installation/3-playground.md deleted file mode 100644 index 28f46c17c3..0000000000 --- a/packages/neo-one-website/docs-old/0-installation/3-playground.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -slug: playground -title: Playground ---- - -The NEO•ONE Playground showcases what's possible with NEO•ONE. - -This guide will walk you through getting started with the [NEO•ONE Playground](https://github.com/neo-one-suite/neo-one-playground). - ---- - -[[toc]] - ---- - -## Requirements - -- [Node](https://nodejs.org) >= 10s.16.0 (We recommend the latest version) -- a package manager: [yarn](https://yarnpkg.com/) **OR** npm (distributed with Node) - ---- - -## Installation - -```bash -git clone https://github.com/neo-one-suite/neo-one-playground.git -cd neo-one-playground -# npm install -yarn install -``` - ---- - -## Compile - -```bash -# npx neo-one build -yarn neo-one build -``` - -This will start up a local network, compile the smart contracts located in the `neo-one/contracts` directory and publish them to your local network. Add `--watch` to listen for changes to the smart contracts and trigger automatic recompilation and deployment. - ---- - -## Start the Playground - -```bash -# npm start -yarn start -``` - -This will open a browser window with the playground. Modify the files in the `src` directory to get a feel for using the NEO•ONE client APIs. - ---- - -## Run the tests - -```bash -# npm test -yarn test -``` - -Smart contract tests in the playground are written in Jest and are located in the `src/__tests__` directory. Play around with them to see how easy it is to test smart contracts! diff --git a/packages/neo-one-website/docs-old/0-installation/config.json b/packages/neo-one-website/docs-old/0-installation/config.json deleted file mode 100644 index ef25c89ade..0000000000 --- a/packages/neo-one-website/docs-old/0-installation/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Installation", - "numbered": false -} diff --git a/packages/neo-one-website/docs-old/1-main-concepts/00-hello-world.md b/packages/neo-one-website/docs-old/1-main-concepts/00-hello-world.md deleted file mode 100644 index d6ce4aa70d..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/00-hello-world.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -slug: hello-world -title: Hello World ---- - -The smallest NEO•ONE smart contract looks like this - -```typescript -export class HelloWorld extends SmartContract {} -``` - -This smart contract doesn't do a whole lot, in fact it does nothing, but this is the smallest compilable smart contract. - ---- - -[[toc]] - ---- - -## How to Read This Guide - -In this guide, we will work through creating a dapp with NEO•ONE starting from writing the smart contract, to building and deploying the smart contract, to testing the smart contract, and all the way up to interacting with the smart contract from a dapp UI. Once you master the basics through this guide, you'll be able to create complex dapps using NEO•ONE. - -::: warning - -Tip - -This guide is designed for people who prefer **learning concepts step by step**. If instead you'd like to learn by doing, check out [NEO•ONE Courses](/course) or the [tutorial](/tutorial). This guide can also serve as a complementary resource to the courses and tutorial. - -::: - -This chapter provides an overview and serves as the first chapter in a step-by-step guide about the main NEO•ONE concepts. In the navigation sidebar you'll find a list of all its chapters. On a mobile device, access the guide navigation by pressing the button in the bottom right corner of your screen. - -Each chapter in this guide builds on the lessons learned in earlier chapters. **You can learn most of NEO•ONE by reading the “Main Concepts” guide chapters in the order they appear in the sidebar.** If you plan to use only one piece of NEO•ONE, then you might find it useful to skip around to the parts that are relevant to you. - ---- - -## Expected Knowledge - -NEO•ONE is a JavaScript library so we'll assume you have a basic understanding of the JavaScript language. **If you're not sure, we recommend taking a [JavaScript tutorial](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) to check your knowledge level**. It might take some time to complete, but then you won't be trying to learn both NEO•ONE and JavaScript at the same time. - -NEO•ONE itself is written in [TypeScript](http://www.typescriptlang.org/) and throughout the guide we will use TypeScript, however the guide assumes no prior knowledge. We will introduce TypeScript specific concepts as they're used, with links to documentation to learn more. - ---- - -## Let's Get Started! - -At the bottom of each page in the guide, including this one, you'll find the link to the [next chapter of the guide](/docs/blockchain-basics) right before the website footer. diff --git a/packages/neo-one-website/docs-old/1-main-concepts/01-blockchain-basics.md b/packages/neo-one-website/docs-old/1-main-concepts/01-blockchain-basics.md deleted file mode 100644 index 942e82b71a..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/01-blockchain-basics.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -slug: blockchain-basics -title: Blockchain Basics ---- - -Blockchain can be a complex concept, but this chapter should help distill down the most important parts required to become an effective dapp developer. - -We'll take a look at some of the foundational technologies of blockchain and learn how they each contribute to the larger picture. If you feel like you already have a strong grasp of blockchain fundamentals and just want to learn about NEO blockchain specifics, feel free to skip to the NEO Specifics section. - ---- - -[[toc]] - ---- - -## Peer to Peer Network - -Blockchain is a large peer to peer network, which means that there is no centralized server or authority. We typically refer to a peer in a blockchain network as a **node**. Each node is equal, though in some blockchains certain nodes have more responsibilities than others by taking on a specific role within the network ecosystem, such as that of a block producing node (sometimes called a miner). Some nodes are referred to as a full node which means they hold a copy of the entire blockchain on a single device. This adds resiliency to the network, as long as a single full node exists with a full copy of the blockchain, the network can be rebuilt. This is one of the key advantages to blockchain compared to traditional client-server models; there is no central point of failure, making it far less vulnerable to being exploited or lost. There is no central or dominant authority and no single party can control the network for their own gain. Blockchain networks are therefore both _distributed_ and _decentralized_. - ---- - -## Cryptography - -Blockchain uses cryptography to maintain network integrity. Once something is recorded on the blockchain, anyone can verify that it was done so legitimately and in a manner that preserves security. In particular, blockchain employs [public-key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography) to secure communication on the network. Public-key cryptography enables users to digitally sign a message with a private key, typically represented as a string of random characters. Anyone can verify that they signed the message using the associated public key for that private key. The public key is generated directly from the private key in a way that cannot be reversed while still enabling the ability to verify that a given digital signature was produced by a particular (unknown) private key. Through public-key cryptography, blockchain is capable of ensuring that any data being recorded onto it has not been tampered with. - -::: warning - -Note - -The public key is typically referred to as the address of a user. In some blockchains, like NEO, a public key is further encoded to produce a valid address. - -::: - ---- - -## Hashing - -A hash function takes an input of any length and uses a mathematical algorithm to produce a fixed length output. Cryptographic hashing takes this one step further by making the hash cryptographically secure. In summary, a cryptographic hash function has several qualities: - -1. Impossible to produce the same hash value from different inputs. -2. The same input will always produce the same hash value. -3. Computationally inexpensive to produce a hash value. -4. Impossible to determine the input based on the hash value. - -Another way to think about hashing is that it produces a unique digital fingerprint of the input. In blockchain, we see hashes everywhere. Transaction hashes are produced by hashing the contents of the transaction and are often referred to as the transaction id or TXID. Block hashes are produced by hashing the contents of the block. - ---- - -## Blockchain Data Structure - -Blockchain at it's core is just a data structure. It's a linked list of blocks where links are direct references to the previous block's hash. Since the previous block's hash is part of the content of the block, it makes it difficult to tamper with the blockchain. For example, changing the 10th block in the blockchain would change the hash of not only that block, but every block afterwards, making changes easy to detect. - -In addition to the hash of the previous block, block's contain: - -1. Root of the transaction hash tree (Merkle Tree). -2. Timestamp at which the block was produced. -3. Index of the block within the blockchain -4. Transactions (not included in the hash, instead the root of Merkle Tree is included) - -::: warning - -Note - -You might be wondering why a [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree) is used rather than just hashing the list of transactions. In short, a Merkle Tree is an efficient way to not only produce the hash of a given set of hashes, but also to enable verification that a given hash exists within the set. - -::: - -Transactions are simply a store of data. In Bitcoin, for example, they are comprised of a data structure of inputs and outputs that represent financial transactions. This system is called unspent transaction outputs, or UTXO, for short. NEO adopts this system for its native assets, NEO and GAS, which we'll discuss more later in this chapter. - -In NEO as well as other smart contract platforms like Ethereum, the transaction also contains the script to run on the platform's virtual machine. - ---- - -## Consensus - -Consensus is the mechanism by which the peer-to-peer networks comes to agreement on the next block to add to the blockchain. There are two main consensus algorithms, Proof of Work (PoW) and Proof of Stake (PoS), from which many variations are produced. PoW requires miner nodes to solve cryptographic puzzles in order to earn the right to add blocks to the chain. PoS requires block producing nodes to stake value (currency) in order to earn the right to add blocks to the chain. In both cases, nodes are incentivized to act honestly and to not produce blocks that have been tampered with or break the rules of the blockchain. The key insight is that acting dishonestly is both easily detectable by other nodes on the network and that by having a block rejected there is an economic penalty. In PoW the economic penalty comes in the form of cost to produce the block - that is, the pure resource cost (energy, price of equipment) required to solve the cryptographic puzzles. In PoS the economic penalty results from a punishment for acting dishonestly, that is, a portion of the staked currency is taken by the network. - -Delegated Proof of Stake (dPOS) works in a similar way to PoS, however instead of block producing nodes staking to earn the right to produce blocks, the users of the network vote on nodes with weight proportional to their holdings. In this system nodes are incentivized to act honestly, otherwise they will be voted out. Voters are incentivized to vote for nodes that will act honestly because the integrity of the network is at stake, and thus the value of their holdings. - ---- - -## NEO Specifics - -NEO's blockchain data structure is very similar to other blockchains and the general outline we gave above. Like Bitcoin, NEO uses the UTXO model for its native assets, NEO and GAS. Like Ethereum, NEO is a full smart contract platform with its own virtual machine. - -One differentiating factor to be aware of is that NEO has several different types of transactions that can be included in a block; we'll list the most important ones below: - -1. `ContractTransaction` - Used for transferring native assets. May only contain inputs and outputs. -2. `InvocationTransaction` - Used for invoking smart contracts. May contain inputs and outputs. -3. `ClaimTransaction` - Used for claiming accrued GAS - -Take a look at the [@neo-one/client](/reference/@neo-one/client) reference for more details on the specific properties stored on each transaction type. Note the final transaction in that list, the `ClaimTransaction`, refers to claiming GAS. GAS is produced every block and allocated to every NEO holder in proportion to their holdings. NEO holders claim their GAS by submitting a `ClaimTransaction` to the network. GAS is used to "fuel" the network; it's used primarily for transaction fees and is also meant as the primary currency. NEO, on the other hand, is meant to represent ownership of the network and is used only for voting and generating GAS. - -NEO uses a form of dPOS called Delegated Byzantine Fault Tolerance (dBFT). While we won't go into detail on the algorithm, the key differentiator of dBFT is that it results in one block finality. Once a block has been propagated on the network it cannot be reversed. Contrast this with most blockchain consensus algorithms which can have anywhere from 6 blocks to 40 or more block finality. NEO holders vote in consensus nodes which participate in producing new blocks via dBFT. diff --git a/packages/neo-one-website/docs-old/1-main-concepts/02-smart-contract-basics.md b/packages/neo-one-website/docs-old/1-main-concepts/02-smart-contract-basics.md deleted file mode 100644 index e39a2d37a1..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/02-smart-contract-basics.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -slug: smart-contract-basics -title: Smart Contract Basics ---- - -NEO•ONE enables writing NEO smart contracts in TypeScript. This chapter will cover the basics of smart contract authoring. - ---- - -[[toc]] - ---- - -## Why TypeScript? - -The first question you might ask is "why should I write my smart contract in TypeScript?" Aside from the many benefits of first-class integration in the NEO•ONE toolchain, there are many standalone advantages to NEO•ONE TypeScript smart contracts. - -1. TypeScript smart contracts enforce strict static types, adding an extra safety net of protection against bugs in your code compared to untyped languages. -2. We can offer an experience that is almost identical to writing normal TypeScript code that runs in the browser or in Node, due to strong support for leveraging the TypeScript type checker within the NEO•ONE compiler. -3. TypeScript has a strong and growing ecosystem built around it - linters, editor support, documentation and tutorials. -4. With inline NEO•ONE compiler diagnostics (in addition to the normal TypeScript diagnostics), you're never left wondering if a particular piece of syntax or logic is supported by the NEO•ONE compiler. - -The NEO•ONE toolchain currently only supports TypeScript smart contracts due to the wealth of static type information they provide. In the future we'd like to support other languages, but for now we highly recommend writing your smart contracts in TypeScript, even if you've never written TypeScript before. - ---- - -## Toolchain - -If you haven't already, prepare your project by following the instructions in the [Environment Setup](/docs/environment-setup) section. - -The NEO•ONE toolchain expects all smart contracts in your project to be contained within one parent folder. By default, that folder is `one/contracts`, though this location is [configurable](/docs/config-options). The main command you'll use from the NEO•ONE toolchain is: - -```bash -neo-one build -``` - -This command compiles your smart contracts, sets up a local private network, deploys your smart contracts to that network and generates testing utilities and client APIs for interacting with your smart contract. Appending the command with `--watch` will watch for changes in your smart contracts and automatically run the build command. - ---- - -## First Steps - -Every NEO•ONE smart contract starts with a TypeScript source file that exports a single [class](https://www.typescriptlang.org/docs/handbook/classes.html) extending `SmartContract`. The simplest smart contract looks like: - -```typescript -export class HelloWorld extends SmartContract {} -``` - -::: warning - -Note - -Throughout the guide and examples elsewhere in the documentation, we will refrain from explicitly importing values to keep the examples short and to the point. All values that are not global can be imported from `'@neo-one/smart-contract'` - -::: - ---- - -## Mental Model - -While the above smart contract is just a shell and doesn't look like it does much, it does have an implicit `constructor` which allows us to create new instances of the class using `new HelloWorld()`. However, unlike a normal TypeScript program, we won't ever explicitly construct instances of a smart contract. Instead, the way to think about your smart contract is that on deployment to the blockchain we automatically construct an instance of it. We then use that one instance for all smart contract method calls. In essence, the smart contract class follows the [singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern). diff --git a/packages/neo-one-website/docs-old/1-main-concepts/03-standard-library.md b/packages/neo-one-website/docs-old/1-main-concepts/03-standard-library.md deleted file mode 100644 index 50bec9be16..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/03-standard-library.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -slug: standard-library -title: Standard Library ---- - -NEO•ONE includes a library of standard smart contract values, functions, interfaces and classes. - -This chapter will go into detail on some of the more common values and types that we will use throughout the guide. While working through the rest of the chapters you may want to keep this page handy. - -For more details, check out the [Smart Contract](/reference/@neo-one/smart-contract) reference. - ---- - -[[toc]] - ---- - -## Value Types - -The standard library includes several specialized value types which are defined in a way that makes them difficult to use incorrectly. For example, it's a static compile time error to pass an `Address` where a `Hash256` is expected, even though both are really just [`Buffer`s](https://nodejs.org/api/buffer.html) underneath the hood. - -- `Address` - a `Buffer` that represents a NEO address. -- `Hash256` - a `Buffer` that represents a NEO 256 bit hash, most commonly used for asset ids like `NEO` or `GAS` asset ids. -- `PublicKey` - a `Buffer` that represents a public key. - -Each of the value types can be created from a string literal using the `from` [static method](https://www.typescriptlang.org/docs/handbook/classes.html#static-properties), for example, `Address.from('APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR')`. `Hash256` also contains static properties for the `NEO` and `GAS` `Hash256` values. - -The `Address` type has a commonly used static method, `isCaller`, which is used to check that the passed `Address` directly called and approved the current method invocation. - -```typescript -Address.isCaller(address); -``` - -`Address.isCaller` should be used whenever you want to take an action for a given `Address`. For example, you would want to check `Address.isCaller(address)` before transferring tokens from the `address` to another party. - ---- - -## Tagged Types - -Tagged types are the same as their underlying type, but we've "tagged" them with a piece of compile-time data. NEO•ONE currently contains two tagged types, and their tags are used exclusively for generating the corresponding NEO•ONE client APIs for the smart contract. The most common tagged type and the only one we'll use throughout the guide is the `Fixed` type. - -The `Fixed` type tags a `number` with the number of decimals that it represents. All `number`s in TypeScript smart contracts are integers since there are no floating point values in smart contracts. However, we typically consider the values we're working with to have decimals from the user's point of view and `Fixed` helps capture that notion. - -For example, the `Fixed<2>` type tells the NEO•ONE toolchain that the integer value represents a fixed point decimal with 2 places. In other words, when we have the value `1250` in a smart contract, it really means `12.50` to the user. The NEO•ONE toolchain uses this information to generate client APIs that automatically convert from the integer representation to the decimal point representation and visa-versa. - -This makes it easy to do things like display the result of a smart contract method invocation that returns a `Fixed<2>`. Simply convert it to a string since the client APIs have already converted it to the decimal representation. Similarly, for dapp inputs, simply take the user's decimal value and pass it directly to the NEO•ONE client APIs, under the hood it will convert appropriately. - ---- - -## Blockchain and Transaction Information - -The `Blockchain` value contains several properties pertaining to the current state of the blockchain, the current transaction and the current invocation: - -- `Blockchain.currentBlockTime` - the timestamp of the `Block` that this `Transaction` will be included in. -- `Blockchain.currentHeight` - index of the last `Block` persisted to the blockchain. -- `Blockchain.currentTransaction` - the current `InvocationTransaction`. -- `Blockchain.currentCallerContract` - the `Address` of the smart contract that directly invoked this contract. May be `undefined` if the current invocation was not from another smart contract. - ---- - -## Opaque Tag Symbol - -If you look at the definition file for the standard library, you might notice a property `OpaqueTagSymbol0`, `OpaqueTagSymbol1`, `one0` or `one1` that is present on all types, including global types like `Array` or `Map`. In order to emit the most efficient NEO VM bytecode possible, we have specialized implementations of all of the standard library types. One limitation of this approach, however, is that you must explicitly use the types. For example, you can't pass an `Array` where an `Array`-like but not `Array` interface is expected. Adding the `OpaqueTagSymbol0`, `OpaqueTagSymbol1`, `one0`, or `one1` properties helps enforce this as a static type error, but it does not catch all cases (though we're working on improving this). - -As a rule of thumb, don't rely on ["Duck Typing"](https://en.wikipedia.org/wiki/Duck_typing), instead always be explicit about the types you're using. - -## JavaScript Semantics - -The NEO•ONE compiler is as close to regular TypeScript as possible. But there are a few areas where our compiler does not exactly match normal JavaScript semantics. These areas almost never come up, but could cause strange behavior if you are expecting your Smart Contract code to behave exactly like JavaScript. One of those is when using native `Map`s and `Set`s. In normal JavaScript if you use a structural type as a key in a `Map` or a member in a `Set`, you can only retrieve that key/member later if it's the same reference. Trying to retrieve that key/member with the same value of a different reference will not work in regular JavaScript. But it WILL work in our compiler. The best way to demonstrate this is with examples. - -### `Set` Example - -This test would pass in regular TS: - -```typescript -const x = new Set>(); -const y = [0]; -const z = [0]; -x.add(y).add(z); - -assertEqual(x.has(y), true); -assertEqual(x.has(z), true); -assertEqual(x.has([0]), false); // notice difference here -assertEqual(x.size, 2); // notice difference here - -x.delete(y); -assertEqual(x.delete(z), true); // notice difference here -assertEqual(x.delete(z), false); -assertEqual(x.size, 0); -assertEqual(x.has(y), false); -assertEqual(x.has(z), false); -``` - -But this test will pass in our TS compiler: - -```typescript -const x = new Set>(); -const y = [0]; -const z = [0]; -x.add(y).add(z); - -assertEqual(x.has(y), true); -assertEqual(x.has(z), true); -assertEqual(x.has([0]), true); // notice difference here -assertEqual(x.size, 1); // notice difference here - -x.delete(y); -assertEqual(x.delete(z), false); // notice difference here -assertEqual(x.delete(z), false); -assertEqual(x.size, 0); -assertEqual(x.has(y), false); -assertEqual(x.has(z), false); -``` - -### `Map` Example - -This test would pass in regular TS: - -```typescript -const x = new Map, string>(); -const y = [0]; -const z = [0]; -x.set(y, 'bar').set(z, 'baz'); - -assertEqual(x.get(y), 'bar'); // notice difference here -assertEqual(x.has(y), true); -assertEqual(x.get(z), 'baz'); -assertEqual(x.has(z), true); -assertEqual(x.get([0]), undefined); // notice difference here -assertEqual(x.has([0]), false); // notice difference here -assertEqual(x.size, 2); // notice difference here - -x.delete(y); -assertEqual(x.delete(z), true); // notice difference here -assertEqual(x.delete(z), false); -assertEqual(x.size, 0); -assertEqual(x.get(y), undefined); -assertEqual(x.has(y), false); -assertEqual(x.get(z), undefined); -assertEqual(x.has(z), false); -``` - -But this test will pass in our TS compiler: - -```typescript -const x = new Map, string>(); -const y = [0]; -const z = [0]; -x.set(y, 'bar').set(z, 'baz'); - -assertEqual(x.get(y), 'baz'); // notice difference here -assertEqual(x.has(y), true); -assertEqual(x.get(z), 'baz'); -assertEqual(x.has(z), true); -assertEqual(x.get([0]), 'baz'); // notice difference here -assertEqual(x.has([0]), true); // notice difference here -assertEqual(x.size, 1); // notice difference here - -x.delete(y); -assertEqual(x.delete(z), false); // notice difference here -assertEqual(x.delete(z), false); -assertEqual(x.size, 0); -assertEqual(x.get(y), undefined); -assertEqual(x.has(y), false); -assertEqual(x.get(z), undefined); -assertEqual(x.has(z), false); -``` diff --git a/packages/neo-one-website/docs-old/1-main-concepts/04-properties-and-storage.md b/packages/neo-one-website/docs-old/1-main-concepts/04-properties-and-storage.md deleted file mode 100644 index 05d7a27b10..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/04-properties-and-storage.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -slug: properties-and-storage -title: Properties and Storage ---- - -NEO•ONE stores persistent data in the class properties of the smart contract. - ---- - -[[toc]] - ---- - -## Properties and Accessors - -Using the mental model of a singleton instance of our smart contract, it becomes clear that all properties of the smart contract are automatically persisted between invocations of the smart contract, just like a normal class instance. In TypeScript we can declare several types of instance properties of a class - [private, protected, public and readonly](https://www.typescriptlang.org/docs/handbook/classes.html#public-private-and-protected-modifiers). The following example explores each of these: - -```typescript -export class HelloWorld extends SmartContract { - public mutableString = 'goodnightMoon'; - public readonly string = 'goodnightMoon'; - protected mutableNumber = 0; - protected readonly number = 0; - private mutableBoolean = true; - private readonly boolean = true; -} -``` - -Each property uses the property initializer syntax which sets the initial value at construction. - -One thing to consider in the mental model of smart contracts is that at a low-level smart contracts only have methods. So when we define a `public` `readonly` property, it will be translated to a method of the same name that takes no arguments and returns the current value of the property. A `public` mutable property, like `mutableString` above, will translate to two methods, a method of the same name that takes no arguments and returns the current value of the property and a method called `set` that takes one argument and sets the value of that property to the argument. For example, `mutableString` will translate to `mutableString` and `setMutableString` methods. - -[Property accessors](https://www.typescriptlang.org/docs/handbook/classes.html#accessors) work identically to properties in terms of the low-level translation to exposed smart contract methods. - -::: warning - -Note - -Properties declared as `protected` or `private` are only "private" within the scope of TypeScript - all NEO smart contracts have fully public storage, so no property is ever truly private. In other words, do not store sensitive data within a `private` property with the expectation that no one can view it - -::: - ---- - -## Structured Storage - -Properties work well for storing primitive values and while you can use an `Array`, `Set` or `Map` as a property for storing structured data, this will store the entire container in a single key in smart contract storage. This is not very efficient, so instead NEO•ONE offers similarly named `ArrayStorage`, `SetStorage` and `MapStorage` classes. These classes are special in that they may only be used as properties of a smart contract class: - -```typescript -export class HelloWorld extends SmartContract { - private readonly mapStorage = MapStorage.for(); - private readonly setStorage = SetStorage.for(); - private readonly arrayStorage = ArrayStorage.for(); -} -``` - -Notice that we construct the structured storage classes using the [static](https://www.typescriptlang.org/docs/handbook/classes.html#static-properties) `for` method and 1-2 [type parameters](https://www.typescriptlang.org/docs/handbook/generics.html), which makes it read as " for ". For example, the `mapStorage` property is a "MapStorage for string to number". - -Aside from the limitations mentioned above, each of the structured storage classes work identically to their `Array`, `Set` and `Map` counterparts. - ---- - -## Storage Types - -The only limitation on storage types is that you cannot use an instance of a class or a functon. This is because we cannot reliably serialize and deserialize arbitrary instances when we store the values in the underlying smart contract storage. For similar reasons, we cannot store arbitrary functions. However, you may declare a `readonly` property that is a function. This can be useful for declaring event notifiers as properties of the class: - -```typescript -export class Contract extends SmartContract { - private readonly notifyTransfer = createEventNotifier
>( - 'transfer', - 'from', - 'to', - 'amount', - ); -} -``` - -We'll learn more about event notifiers in a later chapter of the guide. diff --git a/packages/neo-one-website/docs-old/1-main-concepts/05-methods.md b/packages/neo-one-website/docs-old/1-main-concepts/05-methods.md deleted file mode 100644 index e0f5c899f1..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/05-methods.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -slug: methods -title: Methods ---- - -Methods are the core component of smart contract logic. - ---- - -[[toc]] - ---- - -## Constructor - -The constructor of the smart contract is invoked exactly once on deployment of the smart contract. The constructor can have parameters so that you can deploy with different values on the MainNet vs TestNet vs a local private network, but they must always have a [default](https://www.typescriptlang.org/docs/handbook/functions.html#optional-and-default-parameters) value. The default value is used during automatic deployment to your local private network during manual testing, as well as to the private network used during automated unit tests, so it's typically best to choose defaults that tailor to those two deployments. For example, you might set a time dependent property to a parameter with a default that is computed based on the current time, or you might set an `Address` property, such as the owner, to the current sender address: - -```typescript -export class HelloWorld extends SmartContract { - public constructor( - // Blockchain.currentBlockTime contains the timestamp of the current block, i.e. the block that - // the transaction which invoked this method is included in. - public readonly startTime = Blockchain.currentBlockTime + 60 * 60, - // Deploy.senderAddress is a special property that is filled in with the Address - // of the user who deployed the contract. - public readonly owner = Deploy.senderAddress, - ) {} -} -``` - -Note in this example we've used [parameter properties](https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties) which are a shortcut for declaring a constructor parameter and instance property with a single declaration. - ---- - -## Instance Methods - -Public instance methods come in several flavors but they effectively break down into 3 categories: - -1. Normal instance methods. These have no restrictions and work identically to instance methods in normal TypeScript. -2. Constant instance methods. Designated with the `@constant` decorator, these methods may not modify smart contract properties. -3. Native asset instance methods. Designated with the `@receive`, `@sendUnsafe`, `@send` and `@claim` decorators. Read more about these in the [Native Assets](/docs/native-assets) advanced guide. - -Public instance methods define the API of the smart contract. In the following example we have two methods. One is a constant method since it's decorated with `@constant`. The other is a normal instance method which modifies the smart contract property `mutableClosing`. - -```typescript -export class HelloWorld extends SmartContract { - private mutableClosing = 'goodbye'; - - public setClosing(closing: string): void { - this.mutableClosing = closing; - } - - @constant - public goodbyeMoon(value: string): string { - return `${this.mutableClosing} ${value}`; - } -} -``` - -Private and protected instance methods are just helper methods, same as normal TypeScript, but be aware that any private or protected methods invoked from a public method must respect the restrictions of the public method. For example, you can't call a private or protected method which modifies a smart contract property from a `@constant` public method. - ---- - -## Parameter and Return Types - -Similar to storage properties, parameter and return types for public instance methods may not be classes or functions. diff --git a/packages/neo-one-website/docs-old/1-main-concepts/06-events-and-logs.md b/packages/neo-one-website/docs-old/1-main-concepts/06-events-and-logs.md deleted file mode 100644 index eebe7136be..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/06-events-and-logs.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -slug: events-and-logs -title: Events and Logs ---- - -Smart contracts may emit events to allow listeners to _react_ to changes in smart contract state. - ---- - -[[toc]] - ---- - -## Events - -Decentralized apps commonly need to know the current state of a smart contract, sometimes by employing a centralized storage solution, For example, they may employ a relational database to store the current state in a more efficiently queryable way. Rather than poll the smart contract for the entire state every block, we can react to events emitted by the contract which represent the important state changes. - -Create an event notifier using `createEventNotifier` and then call it to emit an event: - -```typescript -const notifyActionHappened = createEventNotifier>('actionHappened', 'target', 'value'); - -export class HelloWorld extends SmartContract { - public action(target: Address, value: Fixed<8>): boolean { - notifyActionHappened(target, value); - - return true; - } -} -``` - -The `createEventNotifier` function requires an event name as the first argument, and any number of strings that define the event parameter names as the following arguments. For each event parameter name, you must define the type of that parameter using a [type parameter](http://www.typescriptlang.org/docs/handbook/generics.html). In the example above, we've defined an event called `'actionHappened'` with two parameters: - -1. `target` which is an `Address` -2. `value` which is a `Fixed<8>` - -Events must be unique throughout a smart contract. - ---- - -## Debugging with Logs - -Smart contract debugging with NEO•ONE is as simple as adding a `console.log` statement wherever you would in a normal JavaScript program to aid in debugging. All types can be logged as well as converted to strings in a similar fashion to `console.log` in a JavaScript program. The logs will be printed in your terminal when executing smart contract methods through Node. They will also be printed to the developer tools console in your browser. - -Don't forget to remove the `console.log` statements before going to production! diff --git a/packages/neo-one-website/docs-old/1-main-concepts/07-calling-smart-contracts.md b/packages/neo-one-website/docs-old/1-main-concepts/07-calling-smart-contracts.md deleted file mode 100644 index 564918219b..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/07-calling-smart-contracts.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -slug: calling-smart-contracts -title: Calling Smart Contracts ---- - -Smart contracts are not very useful in isolation, they typically interact with other smart contracts that make up the building blocks of a larger piece of infrastructure. - ---- - -[[toc]] - ---- - -## Calling One of Your Smart Contracts - -Calling another one of your smart contracts requires using `LinkedSmartContract.for`. Given the following contract in `Foo.ts`: - -```typescript -export class Foo extends SmartContract { - public takeAction(): boolean { - return true; - } -} -``` - -We can get the singleton instance of `Foo` using `LinkedSmartContract.for()`: - -```typescript -import { Foo } from './Foo'; - -export class Bar extends SmartContract { - public callOtherContract(): boolean { - const foo = LinkedSmartContract.for(); - return foo.takeAction(); - } -} -``` - -Once we have an instance of the contract we can access any of its public properties and methods. Events from the original contract are also propagated automatically and are made available in the NEO•ONE client APIs. - ---- - -## Calling an Arbitrary Smart Contract - -Continuing from the examples above, let's say we want to invoke the `takeAction` method of a smart contract at a given arbitrary `Address`. Similar to `LinkedSmartContract.for`, we can get the instance of the smart contract using `SmartContract.for(address)` where `address` is the `Address` of the smart contract: - -```typescript -interface Foo { - readonly takeAction: () => boolean; -} -declareEvent('actionTaken', 'value'); - -export class Bar extends SmartContract { - public callOtherContract(address: Address): boolean { - const foo = SmartContract.for(address); - return foo.takeAction(); - } -} -``` - -Notice that we also have to define the interface of the smart contract explicitly. The instance returned by `SmartContract.for` will match the interface we've defined and then we can access any of its public properties and methods. - -We also have to declare the events we expect to be emitted by the underlying contract explicitly using `declareEvent`. The `declareEvent` method works the same as `createEventNotifier` except it does not return a function that can be called to emit an event. Instead, it just informs the NEO•ONE toolchain that there are additional events that it needs to register with the NEO•ONE client APIs. - -::: warning - -Note - -A common, but advanced, usage pattern for invoking other arbitrary smart contract is to forward argument values to the invoked method. See the advanced guide on [Forward Values](/docs/forward-values) to learn more. - -::: diff --git a/packages/neo-one-website/docs-old/1-main-concepts/08-client-apis.md b/packages/neo-one-website/docs-old/1-main-concepts/08-client-apis.md deleted file mode 100644 index 79196f7afd..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/08-client-apis.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -slug: client-apis -title: Client APIs ---- - -Now it's time to take a look at the client APIs and learn how to interact with smart contracts from a dapp. - -The NEO•ONE client APIs are organized into two packages, `@neo-one/client` which contains the most commonly used functionality, and `@neo-one/client-full` which contains extended but rarely used functionality. In general a dapp developer only needs to concern themselves with the APIs offered by `@neo-one/client`. Learn more about the `@neo-one/client-full` APIs in the [Extended Client APIs](/docs/extended-client-apis) advanced guide. - ---- - -[[toc]] - ---- - -## Client - -The `@neo-one/client` APIs center around instances of the `Client` class. The `Client` class abstracts away user accounts and even how those accounts are provided to your dapp, for example, they might come from an extension like NEX, dapp browser like nOS or through some other integration. - -::: warning - -Tip - -Do not roll your own wallet when creating a dapp. This fractures the ecosystem and in the worst case, requires users to trust every dapp with their private keys. Instead, configure your `Client` to work with one of the existing wallets. Read more in the [User Accounts](/docs/user-accounts) advanced guide. - -::: - -The `Client` class also contains a few methods that may be useful in the course of developing a dapp: - -- `getCurrentUserAccount(): UserAccount | undefined` - Returns the currently selected `UserAccount`. Returns `undefined` if there are no `UserAccount`s. -- `getCurrentNetwork(): NetworkType` - Returns the currently selected network, a string that will be `'main'` for the MainNet, `'test'` for the TestNet, and typically `'local'` for a local private network. -- `getAccount(id: UserAccountID): Promise` - Returns an object containing the native asset balances for a given `UserAccountID`. - -The `Client` class also contains two methods for creating transactions. - -```typescript -class Client { - public async transfer( - amount: BigNumber, - asset: Hash256String, - to: AddressString, - options?: TransactionOptions, - ): Promise>; - public async transfer(transfers: readonly Transfer[], options?: TransactionOptions): Promise; - - public async claim(optionsIn?: TransactionOptions): Promise; -} -``` - -- `transfer` creates a transaction for transferring native assets from the currently selected account (by default) to the specified address(es). -- `claim` creates a transaction for claiming unclaimed GAS for the currently selected account. - -We'll go into more detail on the shape of the `TransactionResult` object and the semantics of creating transactions in the next chapter. - -All methods that relay transactions to the blockchain optionally accept a `TransactionOptions` object (or an extension of it) for customizing the relayed transaction: - -```typescript -interface TransactionOptions { - /** - * The `UserAccount` that the transaction is "from", i.e. the one that will be used for native asset transfers, claims, and signing the transaction. - * - * If unspecified, the currently selected `UserAccount` is used as the `from` address. - * - * DApp developers will typically want to leave this unspecified. - */ - from?: UserAccountID; - /** - * Additional attributes to include with the transaction. - */ - attributes?: readonly Attribute[]; - /** - * An optional network fee to include with the transaction. - */ - networkFee?: BigNumber; - /** - * A maximum system fee to include with the transaction. Note that this is a maximum, the client APIs will automatically calculate and add a system fee to the transaction up to the value specified here. - * - * Leaving `systemFee` `undefined` is equivalent to `new BigNumber(0)`, i.e. no system fee. - * - * A `systemFee` of `-1`, i.e. `new BigNumber(-1)` indicates no limit on the fee. This is typically used only during development. - */ - systemFee?: BigNumber; -} -``` - -Putting this all together, if we wanted to transfer funds to another account, but only if the account is empty, we would do: - -```typescript -const account = await client.getAccount(otherAccountID); -if (account.balances[Hash256.NEO] === undefined) { - await client.transfer.confirmed(new BigNumber(10), Hash256.NEO, otherAccountID.address); -} -``` - -We'll learn more about the `confirmed` property in the next chapter. Also take note of the `Hash256.NEO` property, which works just like the `Hash256.NEO` property in smart contracts and can be imported directly from `@neo-one/client`. - ---- - -## Toolchain Code Generation - -The NEO•ONE toolchain generates many files that contain helpers and APIs that are essential for dapp development. Running `neo-one build` will emit TypeScript files. Let's briefly cover what each one contains. - -::: warning - -Note - -The output directory for generated files is configurable. You can also change the configuration to emit pure JavaScript files instead of TypeScript. See the [Configuration](/docs/configuration) reference for details. - -::: - -For each contract, the toolchain will emit 3 files: - -- `src/neo-one//abi.ts` - Contains the ABI that generates the client smart contract APIs at runtime that we'll discuss in the next chapter. -- `src/neo-one//contract.ts` - Contains the smart contract definition, which contains the ABI, the source maps for the contract and a mapping from network name to deployed address for the smart contract. Initially the network mapping will only contain the `local` network which represents your local development network. Once you deploy your smart contract to the TestNet or MainNet, it will also contain deployed contract addresses for those networks. The client APIs automatically choose which address to work with based on the network of the user account that is initiating the request. This file also contains a helper function for creating the smart contract APIs given a `Client`. -- `src/neo-one//types.ts` - Contains the TypeScript type definitions for the smart contract client APIs. - -5 files will also be emitted that are common to all of your smart contracts: - -- `src/neo-one/client.ts` - Contains helper functions for creating a fully configured `Client`. The `Client` is also configured automatically for local development with 11 user accounts that each have varying amounts of NEO and GAS. Additionally contains helper functions for creating `DeveloperClient`s which can be used to control your local development environment. These are generally passed on to the NEO•ONE Developer Tools which we'll talk about in a later chapter. -- `src/neo-one/react.tsx` - Contains two react components, that when used together allow you to easily access all of the tools you need to write a dapp with React throughout your component tree. Read more in the [React](/docs/react) advanced guide. We also provide similar tools for apps written in [Angular](/docs/angular) or [Vue](/docs/vue)! -- `src/neo-one/sourceMaps.ts` - Contains all of the smart contract source maps. These source maps are not included in the production build in order to reduce the bundle size. -- `src/neo-one/test.ts` - Contains the `withContracts` test helper. We'll learn more about this helper in the following chapters. -- `src/neo-one/contracts.ts` - Contains the `Contracts` type whose properties are the smart contract APIs for your dapp. - ---- - -## Integration - -Integrating the NEO•ONE client APIs in a vanilla JavaScript or TypeScript application is very simple - assuming we have a contract called `Token` and we're in the `src/index.ts` file using the default NEO•ONE toolchain paths: - -```typescript -import { createClient, createTokenSmartContract } from './neo-one'; - -const client = createClient(); -const token = createTokenSmartContract(client); -``` - -Now we can use both the base blockchain APIs offered by the `Client` class and the generated smart contract APIs that correspond to the `Token` contract. - -::: warning - -Note - -As you prepare your dapp for production, you'll likely want to configure additional `UserAccountProvider`s in the `Client`. Learn more about `UserAccount`s and `UserAccountProvider`s in the [User Accounts](/docs/user-accounts) advanced guide. - -::: - ---- - -## Utilities - -`@neo-one/client` exports many utility functions for working with private keys, addresses, public keys and script hashes: - -- The most common come in the form of conversion functions: `To`, for example, `privateKeyToAddress`. See the full list in the [@neo-one/client](/reference/@neo-one/client) reference. -- `createPrivateKey` returns a new private key. -- `decryptNEP2`, `encryptNEP2` and `isNEP2` implement [NEP-2](https://github.com/neo-project/proposals/blob/master/nep-2.mediawiki) diff --git a/packages/neo-one-website/docs-old/1-main-concepts/09-smart-contract-apis.md b/packages/neo-one-website/docs-old/1-main-concepts/09-smart-contract-apis.md deleted file mode 100644 index a29ba417a8..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/09-smart-contract-apis.md +++ /dev/null @@ -1,377 +0,0 @@ ---- -slug: smart-contract-apis -title: Smart Contract APIs ---- - -The generated smart contract client APIs correspond directly with the properties and methods of your smart contract. - -The smart contract APIs are created at runtime based on the generated ABI in `src/neo-one//abi.ts`. The exact structure of the ABI is not too important, we just need to understand what's happening at a high level. For every public property and method of your smart contract, a corresponding method is created on the smart contract object. - ---- - -[[toc]] - ---- - -## Properties - -Each public property is translated to either a single method or two methods: - -- If the property is `readonly`, then it's translated to a method with the same name. -- If the property is mutable, then it's translated to two methods. One that's named the same as the property and serves to fetch the current value. The other is named `set` and serves to set the value of the property. - -Let's take a look at an example: - -```typescript -export class Contract extends SmartContract { - public myValue = 'value'; - public constructor(public readonly owner = Deploy.senderAddress) {} -} -``` - -Then calling the generated helper method `createContractSmartContract`: - -```typescript -const contract = createContractSmartContract(client); -``` - -would result in an object with three properties: - -- `owner(): Promise` - a method that returns a `Promise` which resolves to the current value of the `owner` property of the smart contract. -- `myValue(): Promise` - a method that returns a `Promise` which resolves to the current value of the `myValue` property of the smart contract. -- `setMyValue(value: string): Promise` - a method which takes a `string` parameter to set as the current value of `myProperty` and that returns a `Promise` that resolves to a `TransactionResult` object. We'll talk more about the `TransactionResult` type in the next section. - -Notice how the smart contract client APIs correspond directly with the properties defined in the smart contract. The main difference is that reading properties requires an asynchronous action - we need to make a request to a node to determine the current value. Thus, the methods return a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) which will resolve to a value with the type of the property. - -`setMyValue` works the same as a normal instance method, which we'll cover in the next section. - ---- - -## Methods - -Recall that the smart contract methods we've seen thus far in this guide come in two forms, normal instance methods and constant instance methods - designated by the `@constant` decorator. - -### Constant - -Constant methods correspond 1:1 with generated methods on the smart contract API object. Given the following contract: - -```typescript -export class Contract extends SmartContract { - @constant - public balanceOf(address: Address): Fixed<8> { - return 0; - } -} -``` - -The generated helper method `createContractSmartContract` will return an object with one property: - -- `balanceOf(value: AddressString): Promise` - a method that returns a `Promise` which resolves to the result of calling `balanceOf` on the smart contract with the provided `address`. - -Later in this chapter we'll provide a type conversion table that elaborates how types are converted from the smart contract APIs to the client APIs. - -### Normal - -Unlike constant methods and reading property values, normal methods require submitting a transaction to the blockchain for processing. The NEO•ONE client APIs model this with a 2 step process: - -1. Construct and relay the transaction to the blockchain. -2. Wait for the transaction to be confirmed. - -Given the following smart contract: - -```typescript -export class Contract extends SmartContract { - public transfer(from: Address, to: Address, amount: Fixed<8>): boolean { - return true; - } -} -``` - -The smart contract object returned by `createContractSmartContract` will contain one property: - -```typescript -transfer(from: AddressString, to: AddressString, amount: Fixed<8>): Promise, InvocationTransaction>> -``` - -Calling this method corresponds to the first step in the process. The `Promise` will resolve once the transaction has been relayed to the blockchain. The `TransactionResult` object contains two properties: - -```typescript -interface TransactionResult { - readonly transaction: TTransaction; - readonly confirmed: (options?: GetOptions) => Promise; -} -``` - -The `transaction` property contains the relayed transaction object. In the above case it will be an `InvocationTransaction` since all normal smart contract methods correspond to relaying an `InvocationTransaction` which invokes the method. - -The `confirmed` method corresponds to the second step of the process. Calling `confirmed` returns a `Promise` which resolves once the transaction has been confirmed on and permanently persisted to the blockchain. The `Promise` resolves to a "receipt" of this confirmation. Every transaction receipt contains at least three properties: - -```typescript -interface TransactionReceipt { - /** - * `Block` index of the `Transaction` for this receipt. - */ - readonly blockIndex: number; - /** - * `Block` hash of the `Transaction` for this receipt. - */ - readonly blockHash: Hash256String; - /** - * Transaction index of the `Transaction` within the `Block` for this receipt. - */ - readonly transactionIndex: number; -} -``` - -Normal instance method invocations return a special receipt called an `InvokeReceipt` which contains additional information: - -```typescript -interface InvokeReceipt> extends TransactionReceipt { - /** - * The result of the invocation. - */ - readonly result: InvocationResult; - /** - * The events emitted by the smart contract during the invocation. - */ - readonly events: ReadonlyArray; - /** - * The logs emitted by the smart contract during the invocation. - */ - readonly logs: ReadonlyArray; - /** - * The original, unprocessed, raw invoke receipt. The `RawInvokeReceipt` is transformed into this object (the `InvokeReceipt`) using the ABI to parse out the events and transaction result. - */ - readonly raw: RawInvokeReceipt; -} -``` - -The `result` property indicates success or failure based on the `state` property of the object - either `'HALT'` for success, or `'FAULT'` for failure. On success, the return value of the invocation is stored in the `value` property of the object. On failure, a descriptive message of the reason why the transaction failed is stored in the `message` property. - -```typescript -interface InvocationResultBase { - /** - * GAS consumed by the operation. This is the total GAS consumed after the free GAS is subtracted. - */ - readonly gasConsumed: BigNumber; - /** - * The total GAS cost before subtracting the free GAS. - */ - readonly gasCost: BigNumber; -} - -interface InvocationResultSuccess extends InvocationResultBase { - /** - * Indicates a successful invocation - */ - readonly state: 'HALT'; - /** - * The return value of the invocation. - */ - readonly value: TValue; -} - -interface InvocationResultError extends InvocationResultBase { - /** - * Indicates a failed invocation - */ - readonly state: 'FAULT'; - /** - * Failure reason. - */ - readonly message: string; -} -``` - -Both successful and failed invocation results contain properties for the total GAS consumed and cost. - -Putting this all together, a common pattern for invoking smart contract methods is the following: - -```typescript -// Indicate in the UI that the transaction is being relayed. - -const result = await contract.transfer(from, to, amount); - -// Indicate in the UI that we're waiting for confirmation -// and process the transaction that was relayed -const transaction = result.transaction; - -const receipt = await result.confirmed(); -if (receipt.result.state === 'FAULT') { - // Handle the failure, possibly processing the error message for display in the UI -} else { - // Do something with the result of the call - const value = receipt.result.value; - // Do something with the emitted events - const events = receipt.events; -} -``` - -### Confirmed Transaction Shortcut - -Every normal instance method also contains a `confirmed` property which is a shortcut for the above process. The `Promise` it returns instead resolves once the transaction is both relayed and confirmed: - -```typescript -// Indicate in the UI that the transaction is being processed (both relayed and confirmed). - -const result = await contract.transfer.confirmed(from, to, amount); - -// Process the transaction that was relayed AND confirmed -const transaction = receipt.transaction; - -if (receipt.result.state === 'FAULT') { - // Handle the failure, possibly processing the error message for display in the UI -} else { - // Do something with the result of the call - const value = receipt.result.value; - // Do something with the emitted events - const events = receipt.events; -} -``` - -The only difference is the `Promise` resolves with an additional property, `transaction`, on the receipt object that contains the `Transaction` that was relayed and confirmed. - ---- - -## Common Properties - -In addition to the generated methods mentioned above, the smart contract object contains a few common properties: - -```typescript -interface SmartContract> { - /** - * The `SmartContractDefinition` that generated this `SmartContract` object. - */ - readonly definition: SmartContractDefinition; - /** - * The underlying `Client` used by this `SmartContract`. - */ - readonly client: TClient; - /** - * Iterate over the events emitted by the smart contract. - * - * @returns an `AsyncIterable` over the events emitted by the smart contract. - */ - readonly iterEvents: (options?: SmartContractIterOptions) => AsyncIterable; - /** - * Iterate over the logs emitted by the smart contract. - * - * @returns an `AsyncIterable` over the logs emitted by the smart contract. - */ - readonly iterLogs: (options?: SmartContractIterOptions) => AsyncIterable; - /** - * Iterate over the events and logs emitted by the smart contract. - * - * @returns an `AsyncIterable` over the events and logs emitted by the smart contract. - */ - readonly iterActions: (options?: SmartContractIterOptions) => AsyncIterable; - /** - * Converts a `RawAction`, typically from the raw results found in a `Block` to a processed `Action` or `undefined` if the action is not recognized by the ABI. - * - * @returns `Action` if the `action` parameter is recognized by the `ABI` of the smart contract, `undefined` otherwise. - */ - readonly convertAction: (action: RawAction) => Action | undefined; -} -``` - -Let's go through each in more detail. - -`definition` is simply the `SmartContractDefinition` that generated the smart contract API object. This is the object created by the automatically generated helper method in `src/neo-one//contract.ts`. This is most commonly used to get the current `Address` of the smart contract we're interacting with: - -```typescript -const network = client.getCurrentNetwork(); -const tokenAddress = token.definition.networks[network].address; -``` - -`client` is the `Client` that was used to create the smart contract API object, and is the underlying client used for all smart contract operations. - -`iterEvents` returns an `AsyncIterable` which allows for [asynchronous iteration](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#async-iteration) over all of the events emitted by the smart contract: - -```typescript -for await (const event of contract.iterEvents()) { - // Do something with each event -} -``` - -`iterLogs` is the same as `iterEvents` but for log notifications, i.e. unstructured strings. Note that NEO•ONE smart contracts intentionally do not support nor emit log events because any time you might want to emit a log event, we believe it's more future-proof to emit a structured event. However, when integrating with external contracts, you may want to iterate over the logs that it emits. - -`iterActions` is simply an `AsyncIterable` over both the events and logs of the smart contract in the order that they were seen. - -All of the `iter` methods accept a `SmartContractIterOptions` object: - -```typescript -/** - * Additional optional options for methods that read data from a smart contract. - */ -export interface SmartContractReadOptions { - /** - * The network to read the smart contract data for. By default this is the network of the currently selected user account. - */ - readonly network?: NetworkType; -} - -/** - * Filter that specifies (optionally) a block index to start at and (optionally) a block index to end at. - */ -export interface BlockFilter { - /** - * The inclusive start index for the first block to include. Leaving `undefined` means start from the beginning of the blockchain, i.e. index 0. - */ - readonly indexStart?: number; - /** - * The exclusive end index for the block to start at. Leaving `undefined` means continue indefinitely, waiting for new blocks to come in. - */ - readonly indexStop?: number; -} - -/** - * Additional optional options for methods that iterate over data from a smart contract. - */ -export interface SmartContractIterOptions extends SmartContractReadOptions, BlockFilter {} -``` - -The `SmartContractIterOptions` object allows specifying the `network` to iterate over and the iteration parameters, which block to start from and which block to end at. - -`convertAction` takes a `RawAction` and converts it using the ABI of the smart contract. This conversion includes parsing out the relevant events and automatically converting the raw parameters. See the [Raw Client APIs](/docs/raw-client-apis) documentation for more details. - -::: warning - -Tip - -Read more about asynchronous iteration [here](http://2ality.com/2016/10/asynchronous-iteration.html) - -::: - ---- - -## Type Conversion Table - -| Smart Contract Type | Client API Type | Notes | -| ------------------- | --------------- | ---------------------------------------------------------------------- | -| boolean | boolean | | -| string | string | | -| number | BigNumber | | -| Fixed | BigNumber | Value is automatically converted to a BigNumber with N decimal places. | -| Buffer | BufferString | Hex encoded byte array | -| Address | AddressString | Base58 encoded NEO address | -| Hash256 | Hash256String | Hex encoded string prefixed by '0x' | -| PublicKey | PublicKeyString | Hex encoded string | -| Array | Array | | -| Map | Map | | -| Object | Object | Object properties are follow the same conversions as above | - -Here are some examples of each of the types in the front-end: - -| Client API Type | Example | -| --------------- | ---------------------------------------------------------------------- | -| boolean | `true` | -| string | `'hello world'` | -| BigNumber | `new BigNumber(10)` | -| BigNumber | `new BigNumber(10)` | -| BufferString | `'02028a'` | -| AddressString | `'APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR'` | -| Hash256String | `'0x7f48028c38117ac9e42c8e1f6f06ae027cdbb904eaf1a0bdc30c9d81694e045c'` | -| PublicKeyString | `'02028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef'` | -| Array | `[0, 1, 2]` | -| Map | `new Map().set('hello', 'world');` | -| Object | `{ key: 'value' }` | diff --git a/packages/neo-one-website/docs-old/1-main-concepts/10-testing.md b/packages/neo-one-website/docs-old/1-main-concepts/10-testing.md deleted file mode 100644 index d6401893a8..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/10-testing.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -slug: testing -title: Testing ---- - -Use your favorite unit test framework to test smart contracts using the NEO•ONE client APIs. - ---- - -[[toc]] - ---- - -## withContracts - -The NEO•ONE toolchain generates a helper function called `withContracts` in `src/neo-one/test.ts` that makes testing a breeze: - -```typescript -import { withContracts } from '../neo-one/test'; - -describe('Token', () => { - test('the token has NEP-5 properties', async () => { - await withContracts(async ({ token }) => { - const [name, symbol, decimals, totalSupply, initialBalance, owner] = await Promise.all([ - token.name(), - token.symbol(), - token.decimals(), - token.totalSupply(), - ]); - expect(name).toEqual('Eon'); - expect(symbol).toEqual('EON'); - expect(decimals.toNumber()).toEqual(8); - expect(totalSupply.toNumber()).toEqual(100_000_000); - }); - }); -}); -``` - -By convention, smart contract tests are located in `src/__tests__`, but you can place them wherever you'd like. - -::: warning - -Note - -In all of our examples we'll use [Jest](https://jestjs.io/) for the testing framework, but the `withContracts` function is framework agnostic, so you may use it with any testing framework. - -::: - -The `withContracts` function starts up a fresh network for each test case, compiles all of your smart contracts, deploys them to the local network, pre-configures a `Client` as well as a `DeveloperClient` and creates the smart contract APIs. It then passes these tools as properties of an object to an async callback function where your testing logic should reside. The properties available to your function are: - -```typescript -interface TestOptions { - /** - * The local network name that the smart contracts have been deployed to and the `client` has been configured with. - */ - readonly networkName: string; - /** - * `Client` that has been pre-configured with the master account for the local network as well as each of the accounts in `accountIDs`. - */ - readonly client: Client<{ - readonly memory: LocalUserAccountProvider; - }>; - /** - * `DeveloperClient` that's been configured to point at the local testing network. - */ - readonly developerClient: DeveloperClient; - /** - * `UserAccountID` of the "master" account - the account that contains ~100 million NEO and ~58 million GAS. - * - * This user account is also the currently selected user account in the `Client` and the one that deployed the contracts. - */ - readonly masterAccountID: UserAccountID; - /** - * Private key for the `masterAccountID`. - */ - readonly masterPrivateKey: string; - /** - * 10 additional user accounts that have been configured in the client with varying amounts of NEO and GAS: - * - * At index: - * 0. 0 NEO and GAS - * 1. 1 NEO and GAS - * 2. 10 NEO and GAS - * 3. 100 NEO and GAS - * 4. 1000 NEO and GAS - * 5. 10000 NEO and GAS - * 6. 100000 NEO and GAS - * 7. 1000000 NEO and GAS - * 8. 5 NEO and GAS - * 9. 20 NEO and GAS - */ - readonly accountIDs: readonly UserAccountID[]; -} -``` - -In addition to the properties listed above, the object will contain a smart contract API object property for each smart contract in your project, configured with the `Client` at the `client` property. The example at the beginning of this section shows how you could access the smart contract API for a smart contract called `Token`. - -Within the callback to the `withContracts` function, we can test our smart contracts using the same NEO•ONE client APIs that we use to interact with the contract in production (and that we've discussed over the previous 2 chapters). - -To run tests quickly, the network and clients are setup to run consensus immediately with every transaction. This way, tests do not have to wait for blocks to be produced every 15 seconds. If you'd like to turn off this behavior, or configure other aspects of `withContracts`, you may pass in an options object as the second parameter: - -```typescript -interface WithContractsOptions { - /** - * Ignore compiler warnings. Useful during smart contract development. - * - * Defaults to `false`. - */ - readonly ignoreWarnings?: boolean; - /** - * Automatically deploy smart contracts using the defaults specified in the constructor arguments. - * - * Defaults to `true`. - */ - readonly deploy?: boolean; - /** - * Automatically run consensus whenever a transaction is relayed. - * - * Defaults to `true`. - */ - readonly autoConsensus?: boolean; - /** - * Automatically provide the necessary system fee for every transaction to execute. - * - * Defaults to `true`. - */ - readonly autoSystemFee?: boolean; -} -``` - -For example, to turn off automatic consensus: - -```typescript -describe('Token', () => { - test('has nep-5 properties', async () => { - await withContracts( - async ({ token }) => { - // Test that it has the expected properties - }, - { autoConsensus: false }, - ); - }); -}); -``` - ---- - -## DeveloperClient - -`DeveloperClient` is a class that is configured to point at a local development network. This class provides methods that are useful during testing: - -- `runConsensusNow(): Promise` - trigger consensus to run immediately. -- `fastForwardOffset(seconds: number): Promise` - fast forward the local network by `seconds` into the future. Use this method to test time-dependent smart contracts. -- `fastForwardToTime(seconds: number): Promise` - fast forward to a particular unix timestamp in the future. -- `reset(): Promise` - reset the local network to it's initial state starting at the genesis block. -- `getSettings(): Promise` - Get the current settings of the private network. -- `updateSettings(options: Partial): Promise` - update settings for the private network. Currently only has a property for controlling the seconds per block. -- `getNEOTrackerURL(): Promise` - fetches the NEO Tracker URL for the project. - -Putting it all together, we might test a time dependent ICO contract like so: - -```typescript -describe('Token', () => { - test('allows participation in the ICO during the allotted time', async () => { - await withContracts(async ({ token, developerClient }) => { - // Fast forward to the start of the ICO - await developerClient.fastForwardOffset(60 * 60); - - // Verify that we can participate in the ICO - const receipt = await token.mintTokens.confirmed({ - sendTo: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - }, - ], - }); - if (receipt.result.state === 'FAULT') { - throw new Error(receipt.result.message); - } - expect(receipt.result.value).toBeUndefined(); - - // Fast forward past the end of the ICO - await developerClient.fastForwardOffset(24 * 60 * 60); - - // Verify that contributing after the end of the ICO throws an error. - // We could also do a similar verification above before the start of the ICO. - let error: Error | undefined; - try { - await token.mintTokens.confirmed({ - sendTo: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - }, - ], - }); - } catch (err) { - error = err; - } - expect(error).toBeDefined(); - }); - }); -}); -``` diff --git a/packages/neo-one-website/docs-old/1-main-concepts/11-dapps.md b/packages/neo-one-website/docs-old/1-main-concepts/11-dapps.md deleted file mode 100644 index b9c05712cf..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/11-dapps.md +++ /dev/null @@ -1,144 +0,0 @@ ---- -slug: dapps -title: Decentralized Apps ---- - -Building a decentralized app doesn't have to be hard, use these tools from NEO•ONE to make it quick and easy. - -In addition to the client APIs we've already walked through, there are a few properties on the `Client` that help make your app reactive. We'll also cover using the NEO•ONE Developer Tools to help speed up manual testing of your dapp. - ---- - -[[toc]] - ---- - -## Reactive - -NEO•ONE uses [Observables](http://reactivex.io/) with [RxJS](http://reactivex.io/rxjs) to enable reactivity in dapps. The `Client` class has several `Observable` properties that can be subscribed to in order to update application state and the application UI. The most commonly used is the `block$` property: - -```typescript -class Client { - /** - * Emits a value whenever a block is persisted to the blockchain. - * - * Immediately emits the latest block/network when subscribed to. - */ - public readonly block$: Observable<{ - readonly block: Block; - readonly network: NetworkType; - }>; -} -``` - -The `Observable` emits a value whenever a new block is persisted to the blockchain for the given network. The `network` property corresponds to the currently selected user account's network. The `Observable` automatically updates to start emitting new blocks from another network whenever the underlying network changes due to a change in the selected user account. - -We can update application state that depends on new blocks by subscribing to the `block$` `Observable`: - -```typescript -client.block$.subscribe(({ block, network }) => { - // Update application state using the latest block and network -}); -``` - -::: warning - -Tip - -If you're using React, check out the `FromStream` component in the [React](/docs/react) advanced guide for a streamlined way to integrate `Observable`s in your application. If you're using Angular or Vue, check out the [Angular](/docs/angular) or [Vue](/docs/vue) advanced guides for examples with those frameworks. - -::: - -One common use-case is to update the user balance whenever a new block is persisted. For example, if we're displaying the user's NEO and GAS balance: - -```typescript -client.block$ - .pipe( - switchMap(async () => { - const userAccount = client.getCurrentUserAccount(); - if (userAccount === undefined) { - return undefined; - } - - const account = await client.getAccount(userAccount.id); - - return { neo: account.balances[Hash256.NEO], gas: account.balances[Hash256.GAS] }; - }), - ) - .subscribe((result) => { - if (result === undefined) { - // Update the UI when a user account is not selected - } else { - const { neo, gas } = result; - // Update the UI with the new neo and gas values. - } - }); -``` - -This is a fairly common pattern, so `Client` already exposes an `Observable` for it: - -```typescript -class Client { - /** - * Emits a value whenever a new user account is selected and whenever a block is persisted to the blockchain. - * - * Immediately emits the latest value when subscribed to. - */ - public readonly accountState$: Observable< - | { - readonly currentUserAccount: UserAccount; - readonly account: Account; - } - | undefined - >; -} -``` - -Thus, we can simplify the above example to just: - -```typescript -client.accountState$.subscribe((result) => { - if (result === undefined) { - // Update the UI when a user account is not selected - } else { - const neo = result.account.balances[Hash256.NEO]; - const gas = result.account.balances[Hash256.GAS]; - // Update the UI with the new neo and gas values. - } -}); -``` - -Take a look at the [@neo-one/client](/reference/@neo-one/client) reference for details on all available `Observable`s. - ---- - -## Developer Tools - -NEO•ONE Developer Tools simplify the process of developing and manually testing your dapp. They contain all of the functionality necessary to control your private network: - -- Immediately run consensus -- Fast forward to a future time -- Reset the local network to it's initial state -- Full wallet implementation with the same set of pre-configured wallets as tests -- Settings for controlling automatic consensus and system fees, seconds per block and adding NEP-5 token addresses to the wallet -- Notifications when transactions are confirmed with links to view the transaction on a local NEO Tracker instance - -Enabling the Developer Tools is easy: - -```typescript -const client = createClient(); -const developerClients = createDeveloperClients(); -DeveloperTools.enable({ client, developerClients }); -``` - -Simply use the generated helper functions in `src/neo-one/client.ts` to construct the various clients the Developer Tools require and then call `enable`. - -::: warning - -Note - -If you've integrated NEO•ONE using the [React](/docs/react) advanced guide, then the Developer Tools are automatically enabled with no additional calls or configuration required. - -::: - -When building for production, the Developer Tools are automatically replaced with an empty implementation, so they won't show up for your users nor affect the bundle size. diff --git a/packages/neo-one-website/docs-old/1-main-concepts/12-deployment.md b/packages/neo-one-website/docs-old/1-main-concepts/12-deployment.md deleted file mode 100644 index b31b3555d8..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/12-deployment.md +++ /dev/null @@ -1,144 +0,0 @@ ---- -slug: deployment -title: Deployment ---- - -You've built your smart contract, tested it and built a dapp around it. Now it's time to deploy. - -Productionizing your smart contract for deployment to a network other than your local network requires keeping a few things in mind which we will cover in this chapter. - ---- - -[[toc]] - ---- - -## Deployment Specifics - -### Properties - -Smart contracts may specify an instance property called `properties` to specify some or all of the properties used during deployment: - -```typescript -export class Contract extends SmartContract { - public readonly properties = { - codeVersion: '1.0', - author: 'Alex DiCarlo', - email: 'foo@bar.com', - description: 'This Contract is the best one.', - }; -} -``` - -These properties have no impact on the execution of the contract, they're simply extra metadata that you may permanently attach to the contract on the blockchain. - -### Upgrade - -Every NEO•ONE smart contract automatically contains a public `upgrade` method. This method replaces the smart contract code as well as the static metadata associated with the contract while preserving the smart contract's storage. In other words, this method can be used to change the logic of your smart contract without losing the data. - -In order to make it possible to upgrade your contract, you _must_ specify the `approveUpgrade` `public` method. This method should return a `boolean` indicating if the `upgrade` is approved: - -```typescript -export class Contract extends SmartContract { - public constructor(public readonly owner = Deploy.senderAddress) {} - - public approveUpgrade(): boolean { - return Address.isCaller(this.owner); - } -} -``` - -Using `Address.isCaller(this.owner)` is the most typical approach. - -::: warning - -Note - -If you do not specify the `approveUpgrade` method, it is impossible for you or anyone else to `upgrade` the contract. - -::: - -### Destroy - -All smart contracts have a `protected` method called `destroy` which any method may use to permanently delete the smart contract. Once `destroy` is called the smart contract can no longer be invoked and the storage is no longer accessible. You're not required to have a method that calls `destroy`, but if you do, it should probably look something like: - -```typescript -export class Contract extends SmartContract { - public constructor(public readonly owner = Deploy.senderAddress) {} - - public permanentlyDestroy(): boolean { - if (!Address.isCaller(this.owner)) { - return false; - } - - this.destroy(); - - return true; - } -} -``` - -::: warning - -Note - -While the contract can no longer be invoked and the storage is not accessible, all of the past invocations still exist on the blockchain. The storage can still be accessed by replaying the blockchain from the beginning up until the point it was destroyed. - -::: - ---- - -### Migration File - -To deploy your contract to a network, you will need to define a `migration` file. The default location for this file is `neo-one/migration.ts`, but it can be [configured](/docs/config-options). A migration file simply exports a function to call the deploy method on your smart contracts with the appropriate arguments. It should look something like this: - -```typescript -import BigNumber from 'bignumber.js'; -import { MigrationContracts } from '../src/neo-one'; - -export default ({ token, ico, escrow }: MigrationContracts, _network: string) => { - token.deploy(); - ico.deploy(undefined, new BigNumber(1566864121), undefined); - escrow.deploy(); -}; -``` - -### MigrationSmartContract - -You may have noticed the new type we use in the above `migration` file, `MigrationContracts`. This is another type generated by NEO•ONE for use specifically in `migration` files and while it looks the same as its counterpart `SmartContract` it has a key difference in that there is no `.confirmed(...)` properties for any of its contract methods. This is because during migration _every_ contract invocation will be be awaited before proceeding to this next invocation. This can be useful when you would like to deploy contracts in series or if you would like to do some additional bootstrapping after the deployment of a contract. - -As an example, lets say you have an ICO contract and you would like to make sure you are the first person to mint a portion of the tokens. Then, going off the migration file above, we could run something like: - -```typescript -import BigNumber from 'bignumber.js'; -import { Hash256 } from '@neo-one/client'; -import { MigrationContracts } from '../src/neo-one'; - -export default ({ token, ico, escrow }: MigrationContracts, _network: string) => { - token.deploy(); - // here we set the startTime of the ICO to be immediate - ico.deploy(undefined, new BigNumber(0), undefined); - ico.mintTokens([{ amount: new BigNumber(10), asset: Hash256.NEO }]); - escrow.deploy(); -}; -``` - -This will ensure that after deploying the `ico` contract (and confirming it is deployed) the next action before deploying the `escrow` contract is to mint some of the ICO tokens to the currently selected `UserAccount`. While a more elegant and safe solution might be to allow the owner of the ICO to mint tokens before the timer has started this should make it clear how you can bootstrap a contract during migration. - -## Deploying to a Public Network - -Once you have successfully configured your `migration` file as explained above you are all set to deploy your Smart Contract! Using the set of [networks](/docs/config-options) defined in `.neo-one.config.js` you can deploy using the command: - -```bash -yarn neo-one deploy --network -``` - -where `network` is one of the keys provided by your configuration. By default `yarn neo-one deploy` will use the `test` key. - -::: warning - -Note - -We HIGHLY recommend deploying to both a local private network _and_ the Neo TestNet before attempting to deploy to the MainNet. - -::: diff --git a/packages/neo-one-website/docs-old/1-main-concepts/config.json b/packages/neo-one-website/docs-old/1-main-concepts/config.json deleted file mode 100644 index 3cb4f3e1b2..0000000000 --- a/packages/neo-one-website/docs-old/1-main-concepts/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Main Concepts", - "numbered": true -} diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/00-native-assets.md b/packages/neo-one-website/docs-old/2-advanced-guides/00-native-assets.md deleted file mode 100644 index 43e9fb36a1..0000000000 --- a/packages/neo-one-website/docs-old/2-advanced-guides/00-native-assets.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -slug: native-assets -title: Native Assets ---- - -Native assets like NEO and GAS require special handling in smart contracts. This guide will show you how. - -NEO employs the [Unspent Transaction Output](https://en.wikipedia.org/wiki/Unspent_transaction_output) (UTXO) system for native assets. Unfortunately, the UTXO system does not play well with smart contracts. Fortunately, NEO•ONE smart contracts abstract away most of the difficulty in handling native assets using the `@receive`, `@send`, `@sendUnsafe` and `@claim` [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html). - -One commonality between every native asset method is that they must throw an error if the transaction should not proceed. - ---- - -[[toc]] - ---- - -## Receive Native Assets - -Decorate a method with `@receive` to allow the method to be invoked when receiving native assets: - -```typescript -export class Contract extends SmartContract { - @receive - public mintTokens(): void { - // Use Blockchain.currentTransaction to validate and process the inputs/outputs. - // Throw an error if it's an invalid combination - } -} -``` - -Methods decorated with `@receive` may also be decorated with `@sendUnsafe` to enable both sending and receiving assets to be verified by the method. - -Invoking a method marked with `@receive` is identical to a normal method, but the transaction options contain an additional property, `sendTo`, which can be used to specify the assets to send to the smart contract: - -```typescript -const receipt = await contract.mintTokens({ - sendTo: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - }, - ], -}); -``` - -There are cases where a smart contract may receive native assets without a corresponding `@receive` method invocation, or sometimes even when the `@receive` method throws an error. Unfortunately this is unavoidable, and to solve these cases every smart contract has an automatically generated method called `refundAssets`. Users may call this method when they have sent assets to the contract that were not properly processed. Using the NEO•ONE client APIs: - -```typescript -const transactionHash = ... // Hash of the transaction that needs to be refunded -const receipt = await contract.refundAssets.confirmed(transactionHash); -``` - ---- - -## Send Native Assets - -NEO•ONE provides two methods for sending assets, one that is "unsafe" and one that is "safe". - -### Unsafe - -Decorate a method with `@sendUnsafe` to enable assets to be sent from the contract in a single transaction: - -```typescript -export class Contract extends SmartContract { - @sendUnsafe - public withdraw(): void { - // Typically check something like Address.isCaller(this.owner) - } -} -``` - -`@sendUnsafe` is unsafe because it potentially allows the equivalent of double spends. It's possible for a user to construct a series of parallel transactions that enable them to withdraw more than they should be allowed to. - -::: warning - -Note - -Only decorate a method with `@sendUnsafe` when the method checks that the caller is a "superuser", i.e. someone who is not going to attempt to cheat the contract. The most common case is to simply call `Address.isCaller(this.owner)` which checks that the method was only invoked by the owner of the smart contract. - -::: - -Calling a method marked with `@sendUnsafe` is similar to `@receive` in that it allows an additional options property called `sendFrom` which lets the user specify assets to transfer from the contract: - -```typescript -const receipt = await contract.withdraw.confirmed({ - sendFrom: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - to: 'APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR', - }, - ], -}); -``` - -### Safe - -Decorate a method with `@send` to enable assets to be sent from the contract safely. `@send` requires two transactions to send assets from the contract. At a high level the steps are: - -1. The user "marks" the assets they wish to withdraw from the contract by constructing a transaction that sends those assets back to the smart contract. -2. The user constructs a transaction that withdraws the previously "mark"ed assets to the desired address. - -NEO•ONE abstract this process such that you only need to define a method decorated with `@send` that throws an error on invalid transactions. NEO•ONE handles the rest. This method may also accept a final argument, a `Transfer` object, that contains the details of the pending transfer: - -```typescript -interface Transfer { - readonly amount: Fixed<8>; - readonly asset: Hash256; - readonly to: Address; -} -``` - -For example, if you wanted to have a method that required a single argument, `value`, of type `string`, you could define your method like so: - -```typescript -export class Contract extends SmartContract { - @send - public withdraw(value: string, transfer: Transfer): void { - // Validate the `transfer` should proceed. Throw an error if not. - } -} -``` - -Calling a method marked with `@send` is identical to `@sendUnsafe`, however, the transfer will not occur until the `completeSend` method is invoked with the transaction hash of the first transaction: - -```typescript -// This transaction only sends assets from the contract to itself, -// marking them for withdrawal by a followup transaction. -const receipt = await contract.withdraw.confirmed('value', { - sendFrom: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - to: 'APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR', - }, - ], -}); -// Complete the withdrawal process using the transaction hash -const finalReceipt = await contract.completeSend.confirmed(receipt.transaction.hash); -``` - ---- - -## Claim GAS - -Decorate a method with `@claim` to enable claiming GAS. `@claim` methods have a few restrictions: - -1. `@claim` methods may not modify contract storage. They act like `@constant` methods. -2. `@claim` methods may not access `Blockchain.currentTransaction`, instead they may optionally accept the `ClaimTransaction` that the method was invoked in as the final argument. - -```typescript -export class Contract extends SmartContract { - @claim - public claim(transaction: ClaimTransaction): void { - // Validate the ClaimTransaction and throw an error if it is invalid - } -} -``` - -The NEO•ONE client APIs currently only support claiming all available GAS for a smart contract and sending that GAS back to the smart contract. If you have another use-case that you'd like to see supported, please reach out on [Discord](https://discordapp.com/invite/S86PqDE) or open an issue on [GitHub](https://github.com/neo-one-suite/neo-one/issues/new). - -```typescript -await contract.claim.confirmed(); -``` - -::: warning - -Note - -`@claim` is similar to `@sendUnsafe` in terms of safety and thus you should only allow GAS claims that transfer the GAS to an `Address` that is not the contract itself to be done by superusers. To enable GAS claims for contracts without owners or superusers, instead only allow GAS claims that send the GAS back to the contract, and then implement transferring the GAS to the rightful owner using a method marked with `@send`. - -::: diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/config.json b/packages/neo-one-website/docs-old/2-advanced-guides/config.json deleted file mode 100644 index 62d042b298..0000000000 --- a/packages/neo-one-website/docs-old/2-advanced-guides/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Advanced Guides", - "numbered": false -} diff --git a/packages/neo-one-website/docs-old/3-node/1-docker.md b/packages/neo-one-website/docs-old/3-node/1-docker.md deleted file mode 100644 index 94aff69d6b..0000000000 --- a/packages/neo-one-website/docs-old/3-node/1-docker.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -slug: node-docker -title: Local Docker Development ---- - -In this section we will cover how to deploy a NEO•ONE Node locally using the NEO•ONE Node Docker image. - -If you are unfamiliar with Docker or do not have a version installed locally visit their [getting started](https://www.docker.com/get-started) page. - ---- - -[[toc]] - ---- - -## Requirements - -- [Docker](https://www.docker.com/get-started) - - Minimum: **_at least_** 2GB Memory, 1cpu, and 50GB Storage allocated - - Recommended: 4GB Memory, 2cpu, and 60GB+ Storage allocated - (if you plan to deploy to a cluster you will need this for _each_ pod/container) - -## Getting Started - -NEO•ONE pushes a new node image to [dockerhub](https://hub.docker.com/r/neoonesuite/node) every time a new version is published. We publish a new node image with each commit as well as tagged versions for official releases. We recommend using the most recent tagged version, such as `neoonesuite/node:neo-one-node-binv2.3.0`. - -After you have installed Docker, run the following in a terminal: - -```bash -docker pull neoonesuite/node -docker run neoonesuite/node -``` - -Voila! You should now be running the most recent NEO•ONE Node in a local docker container and will see logs to confirm it has started. Since the NEO•ONE Node uses [pino](https://www.npmjs.com/package/pino) for logging we recommend piping the logs through [pino-pretty](https://github.com/pinojs/pino-pretty) during development. Note that the node won't begin syncing with the blockchain until additional configuration is provided. - -## Configuring - -There are **several** ways to configure the node; any [rc](https://github.com/dominictarr/rc#rc) type configuration is accepted. as an example we can set the `logger` level of the node to _trace_ using either: - -```bash -docker run neoonesuite/node --telemetry.logging.level=trace -``` - -or through environment variables - -```bash -docker run -e neo-one_telemetry__logging__level=trace neoonesuite/node -``` - -Additionally you have the option of creating a `config` (no extension) file and mounting it directly to the container. By default the node will look for a config at `/etc/neo-one`. - -So if we have a config - -```bash -## /path/to/config -{ - "telemetry": { - "logging": { - "level": "trace" - } - } -} -``` - -located at `/path/to/config` we could mount this to the default location as: - -```bash -docker run -v /path/to:/etc/neo-one/ neoonesuite/node -``` - -(Note that you must mount the **entire** folder the config file is in) - -After running any the above you should see more logging on startup! For more configuration options see the [configuration reference](/docs/node-configuration). - -## Storage - -Similarly to how we can mount a configuration folder to the container for local testing we can also mount a folder for storing the blockchain data our node will collect. By default, the node will use `/root/.local/share/neo-one` as its storage. We can mount a local folder `/path/to/node-data/` using - -```bash -docker run -v /path/to/node-data:/root/.local/share/neo-one neoonesuite/node -``` - -This is helpful when testing locally as you won't have to re-sync your node-data on every restart. - -## Port Publishing - -By default the container will be able to access external resources, such as connecting and syncing with other relay nodes after setting `node.rpcURLs`. - -If you would like your local Docker container to be able to send its own data, you'll need to `publish` the port using docker commands. As an example we can enable node metrics using the following command: - -```bash -docker run -p 8001:8001 neoonesuite/node --telemetry.port=8001 -``` - -Upon visiting `localhost:8001/metrics` you should now see the node-metrics page. - -::: warning - -Note - -By default metrics are **disabled** so you _must_ include the `--telemetry.port=8001` argument or provide a telemetry port through other means of configuration (see above). - -::: - -## Examples - -The following configurations should be a solid jumping off point for working with the node. For each of the three examples here we will also show how to implement them using [Docker Compose](/docs/node-compose/). - -In all three examples we will use - -```bash -docker run -v /node-config/:/etc/neo-one/ -v /node-data/:/root/.local/share/neo-one neoonesuite/node -``` - -to mount our configuration and local data file before starting the node. Go ahead and create the two folders `node-config` and `node-data` if you would like to follow along. - -### Sync - -To sync your node with other nodes on the network, you must specify them using the `node.rpcURLs` configuration setting. A list of current mainnet nodes can be found at: http://monitor.cityofzion.io/ - -```bash -#/node-config/config -{ - "node": { - "rpcURLs": [ - "http://seed6.ngd.network:10332", - "http://node1.nyc3.bridgeprotocol.io:10332" - ] - } -} -``` - -Now, if we apply this configuration we can begin to request block information from other nodes. After saving this to `node-config/config`, run the command listed above. - -Upon successfully starting the node, you should begin to see `relay_block` events! - -::: warning - -Note - -Its worth mentioning that syncing the entire blockchain can take a **very** long time. If you plan on syncing/restoring multiple times it might be worth creating a backup of your `node-data` folder. - -::: diff --git a/packages/neo-one-website/docs-old/3-node/2-kubernetes.md b/packages/neo-one-website/docs-old/3-node/2-kubernetes.md deleted file mode 100644 index 8eae821645..0000000000 --- a/packages/neo-one-website/docs-old/3-node/2-kubernetes.md +++ /dev/null @@ -1,401 +0,0 @@ ---- -slug: node-kubernetes -title: Kubernetes ---- - -In this section we will cover how to deploy a NEO•ONE Node to a Kubernetes cluster. - -If you are unfamiliar with Kubernetes visit their [getting started](https://kubernetes.io/docs/tutorials/kubernetes-basics/) page, -in particular we will be implementing a [StatefulSet](https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/) locally using Kubernetes through Docker. - ---- - -[[toc]] - ---- - -## Requirements - -- [Docker](https://www.docker.com/get-started) - - Minimum: **_at least_** 2GB Memory, and 50GB Storage allocated - - Recommended: 4GB Memory, 60GB+ Storage allocated (you will need ~60GB of storage per pod) -- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) - - You can enable Kubernetes through the docker GUI; Docker >> Preferences... >> Kubernetes >> Enable Kubernetes - ---- - -## Getting Started - -The following deployment spec will create a StatefulSet of `n` nodes defined by `spec.replicas`. Each requests 60GB of storage and 4GB of memory. If you do not have a default storage class set (docker will automatically create one for local deployments) you will need to create one, see [storage classes](https://kubernetes.io/docs/concepts/storage/storage-classes/) for more information. - -A requirement of StateFul sets is a headless service, so we'll start by creating `neo-one-service`: - -```yml -#node-svc.yml -apiVersion: v1 -kind: Service -metadata: - name: neo-one-node - labels: - app: neo-one-node -spec: - ports: - - port: 8080 - name: node - clusterIP: None - selector: - app: neo-one-node -``` - -followed by the StatefulSet itself which we'll save as `node-spec.yml`: - -```yml -# node-spec.yml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: node -spec: - serviceName: "neo-one-node" - replicas: 1 - selector: - matchLabels: - app: neo-one-node - template: - metadata: - labels: - app: neo-one-node - spec: - containers: - - name: neo-one-node - image: neoonesuite/node - imagePullPolicy: IfNotPresent - ports: - - containerPort: 8080 - name: node - volumeMounts: - - name: node-data - mountPath: /root/.local/share/neo-one - args: [ - "--node.rpcURLs=http://seed6.ngd.network:10332", - "--node.rpcURLs=https://seed1.red4sec.com:10332" - ] - resources: - requests: - memory: "4Gi" - cpu: "1" - volumeClaimTemplates: - - metadata: - name: node-data - spec: - accessModes: [ "ReadWriteOnce" ] - resources: - requests: - storage: 60Gi -``` - -Running this deployment with - -```bash -kubectl apply -f node-svc.yml -kubectl apply -f node-spec.yml -``` - -will start a single pod which: - -- makes a persistent volume claim for 60GB of storage. -- starts the node with this volume mounted to the default node-storage path -- if node-data isn't present, restore from the public google-cloud backup -- sync the node using two seeds from http://monitor.cityofzion.io/ - -There are two main benefits to deploying the nodes this way. If a pod needs to restart for _any_ reason it will always attempt to bind to the same persistent volume and will not start until it is scheduled on the same machine as that volume. It also makes it incredibly simple to scale the number of nodes you would like to run. - -## Pause/Shutdown - -The simplest way to pause any pods from scheduling/running is by setting `spec.replicas: 0` in your `node-spec.yml` and running - -```bash -kubectl apply -f node-spec.yml -``` - -To purge the persisted volume space and shutdown the headless service you can simply delete both with: - -```bash -kubectl delete svc neo-one-service -kubectl delete statefulset node -``` - -## Configuration - -[Configuration Reference](/docs/node-configuration/) - -While the above examples shows how to configure our pods with environment variables we can also mount a [ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) to our pods. As an example we will use a basic configuration: - -```bash -#/path/to/config.json -{ - "telemetry": { - "logging": { - "level": "debug" - } - } -} -``` - -Creating a ConfigMap is as easy as running: - -```bash -#create the configMap -kubectl create configmap example-config-map --from-file=config=/path/to/config.json -#inspect the configMap -kubectl describe configmap example-config-map -``` - -Then, we can apply the ConfigMap by modifying the node-spec above to the following: - -```yml -# node-spec.yml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: node -spec: - serviceName: 'neo-one-node' - podManagementPolicy: 'Parallel' - replicas: 1 - selector: - matchLabels: - app: neo-one-node - template: - metadata: - labels: - app: neo-one-node - spec: - containers: - - name: neo-one-node - image: neoonesuite/node - ports: - - containerPort: 8080 - name: node - volumeMounts: - - name: node-data - mountPath: /root/.local/share/neo-one - - name: config-volume - mountPath: /etc/neo-one/config - subPath: config - resources: - requests: - memory: '4Gi' - cpu: '1' - volumes: - - name: config-volume - configMap: - name: example-config-map - optional: true - - volumeClaimTemplates: - - metadata: - name: node-data - spec: - accessModes: ['ReadWriteOnce'] - resources: - requests: - storage: 60Gi -``` - -::: warning - -Note - -Because of how [rc](https://www.npmjs.com/package/rc) searches for configuration files the key of the configMap MUST be `config` no extension. - -::: - -## Health Probes - -Sometimes a node will go down and need to be restarted, more commonly a node gets 'stuck' while syncing the blockchain data from other nodes. Because of this it can be extremely useful to configure health probes alongside your pods. - -To enable health checks on the NEO•ONE Node you must first enable the options in your configuration. Assuming you have set up configuration mounting described above the following example `config.json` will enable health checks: - -```json -{ - "node": { - "rpcURLs": [ - "http://seed1.ngd.network:10332", - "http://seed2.ngd.network:10332", - "http://seed3.ngd.network:10332", - "http://seed4.ngd.network:10332", - "http://seed5.ngd.network:10332", - "http://seed6.ngd.network:10332", - "http://seed7.ngd.network:10332", - "http://seed8.ngd.network:10332", - "http://seed9.ngd.network:10332", - "http://seed10.ngd.network:10332", - "https://seed1.cityofzion.io:443", - "https://seed2.cityofzion.io:443", - "https://seed3.cityofzion.io:443", - "https://seed4.cityofzion.io:443", - "https://seed5.cityofzion.io:443" - ] - }, - "network": { - "listenTCP": { - "port": 8081 - } - }, - "rpc": { - "http": { - "port": 8080 - }, - "liveHealthCheck": { - "rpcURLs": [ - "http://seed1.ngd.network:10332", - "http://seed2.ngd.network:10332", - "http://seed3.ngd.network:10332", - "http://seed4.ngd.network:10332", - "http://seed5.ngd.network:10332", - "http://seed6.ngd.network:10332", - "http://seed7.ngd.network:10332", - "http://seed8.ngd.network:10332", - "http://seed9.ngd.network:10332", - "http://seed10.ngd.network:10332", - "https://seed1.cityofzion.io:443", - "https://seed2.cityofzion.io:443", - "https://seed3.cityofzion.io:443", - "https://seed4.cityofzion.io:443", - "https://seed5.cityofzion.io:443" - ] - }, - "readyHealthCheck": { - "rpcURLs": [ - "http://seed1.ngd.network:10332", - "http://seed2.ngd.network:10332", - "http://seed3.ngd.network:10332", - "http://seed4.ngd.network:10332", - "http://seed5.ngd.network:10332", - "http://seed6.ngd.network:10332", - "http://seed7.ngd.network:10332", - "http://seed8.ngd.network:10332", - "http://seed9.ngd.network:10332", - "http://seed10.ngd.network:10332", - "https://seed1.cityofzion.io:443", - "https://seed2.cityofzion.io:443", - "https://seed3.cityofzion.io:443", - "https://seed4.cityofzion.io:443", - "https://seed5.cityofzion.io:443" - ] - } - } -} -``` - -Be sure to apply this new config to your ConfigMap `example-config-map` by running: - -```bash -kubectl delete configmap example-config-map -kubectl create configmap example-config-map --from-file=config=/path/to/config.json -``` - -After our config has been mapped we can add the liveness/readiness configurations to our `node-spec.yml`: - -```yml -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: node -spec: - selector: - matchLabels: - app: neo-one-node - serviceName: 'neo-one-node' - podManagementPolicy: 'Parallel' - replicas: 1 - template: - metadata: - labels: - app: neo-one-node - spec: - containers: - - name: neo-one-node - image: neoonesuite/node - ports: - - containerPort: 8080 - name: node - volumeMounts: - - name: node-data - mountPath: /root/.local/share/neo-one - - name: config-volume - mountPath: /etc/neo-one/config - subPath: config - resources: - requests: - memory: '4Gi' - cpu: '1' - livenessProbe: - httpGet: - path: /live_health_check - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 60 - readinessProbe: - httpGet: - path: /ready_health_check - port: 8080 - initialDelaySeconds: 30 - periodSeconds: 15 - volumes: - - name: config-volume - configMap: - name: example-config-map - optional: true - - volumeClaimTemplates: - - metadata: - name: node-data - spec: - accessModes: ['ReadWriteOnce'] - resources: - requests: - storage: 60Gi -``` - -After starting this StatefulSet with - -```bash -kubectl apply -f node-spec.yml -``` - -you should be able to inspect the state of the health checks (once they start running) with - -```bash -kubectl describe pod node-0 -``` - -see [Kubernetes Documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/#define-readiness-probes) for more information on health probes. - -## Exposing Pods of a StatefulSet Locally - -Since we start our StatefulSet under a headless service we do not have direct access to the underlying endpoints (see [headless services](https://kubernetes.io/docs/concepts/services-networking/service/#headless-services)). The solution to this issue is by creating _another_ service which explicitly targets the pods created by the stateful set. For our single pod example it is as simple as starting a service: - -```yml -#node-0-svc.yml -apiVersion: v1 -kind: Service -metadata: - name: node-0-svc -spec: - type: LoadBalancer - externalTrafficPolicy: Local - selector: - statefulset.kubernetes.io/pod-name: node-0 - ports: - - protocol: TCP - port: 8080 - targetPort: 8080 -``` - -Voilà! You should now be able to access the pod locally! You can test this by running - -```bash -curl localhost:8080/live_health_check -``` diff --git a/packages/neo-one-website/docs-old/3-node/3-docker-compose.md b/packages/neo-one-website/docs-old/3-node/3-docker-compose.md deleted file mode 100644 index 5147a77fcb..0000000000 --- a/packages/neo-one-website/docs-old/3-node/3-docker-compose.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -slug: node-compose -title: Docker Compose ---- - -In this section we will cover how to deploy a NEO•ONE Node to a swarm using Docker Compose. - -If you haven't already be sure to check out the local docker development [section](/docs/node-docker) to familiarize yourself with the container we are deploying. Additionally, brushing up on [Docker-Compose](https://docs.docker.com/compose/) would also be worthwhile. - ---- - -[[toc]] - -## Getting Started - -We'll be deploying with docker-compose using `swarm` mode. The `docker-compose.yml` below is a very similar deployment to what we saw in the [kubernetes](/docs/node-kubernetes) section. We create a persistent named-volume for each container started and run our backup and sync configuration. - -```yml -## docker-compose.yml -version: "3.1" -services: - node: - image: neoonesuite/node - command: [ - "--node.rpcURLs=http://seed6.ngd.network:10332", - "--node.rpcURLs=https://seed1.red4sec.com:10332" - ] - deploy: - replicas: 1 - resources: - limits: - cpus: "1" - memory: 4G - restart_policy: - condition: on-failure - volumes: - - node-data:/root/.local/share/neo-one -volumes: - node-data: -``` - -To start a docker swarm and apply our deployment you can run - -```bash -docker swarm init -docker stack deploy -c docker-compose.yml test -``` - -You can then check this service is running with - -```bash -docker service ls -``` - -Finally, to shutdown this deployment kill the swarm using - -```bash -docker swarm leave --force -``` - -::: warning - -Note - -If you delete the service created by docker, you will still need to cleanup the volume, `node-data` in our example, that is created on startup. You can find the volume using `docker volume ls` and remove it using `docker volume rm `. - -::: - -## Logs - -You can list all of the containers being run using - -```bash -docker container ls -``` - -then to see its logs you can either attach directly to the container (we recommend this only for testing startup as SIGINT will kill the container) with - -```bash -docker attach -``` - -or check its most recent logs - -```bash -docker logs -``` - -## Health Checks - -You can add health checks to a docker swarm similar to a kubernetes setup. After enabling live checks in the NEO•ONE Node configuration we can enable a probe by adding the following to our compose configuration: - -```yml -healthcheck: - test: ['CMD', 'curl', '-f', 'http://localhost:/live_health_check'] - interval: 1m30s - timeout: 10s - retries: 3 - start_period: 45s -``` - -See [docker documentation](https://docs.docker.com/compose/compose-file/#healthcheck) for more information about health check configurations. diff --git a/packages/neo-one-website/docs-old/3-node/4-build-from-source.md b/packages/neo-one-website/docs-old/3-node/4-build-from-source.md deleted file mode 100644 index b00c422f5c..0000000000 --- a/packages/neo-one-website/docs-old/3-node/4-build-from-source.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -slug: node-source -title: Building From Source ---- - -In this brief walk-through we will show you how to build the NEO•ONE Node from source code. - -This can be useful for local debugging and if you would like to make your own contribution to the node repository. - ---- - -[[toc]] - ---- - -## Requirements - -- [Node](https://nodejs.org) >= 10.16.0 (We recommend the latest version) - - Linux and Mac: We recommend using [Node Version Manager](https://github.com/creationix/nvm). - - Windows: We recommend using [Chocolatey](https://chocolatey.org/). -- [Yarn](https://yarnpkg.com/) (recommended) - ---- - -## Build - -Once you have cloned the [NEO•ONE repository](https://github.com/neo-one-suite/neo-one) (or preferably your own fork of the repository) you can run the following to build the node entry point - -```bash -cd neo-one -yarn install -yarn build:node -cd ./dist/neo-one/packages/neo-one-node-bin/bin/ -``` - -`yarn build:node` will build a bin for the node as well as the `@neo-one` packages that it depends on. For this tutorial we will `cd` into the entry point's build directory to save time. Running the new node then is as simple as - -```bash -node neo-one-node -``` - -## Configure - -[Configuration Reference](/docs/node-configuration) - -When running the node locally it is quite easy to apply a configuration file compared to docker since we don't have to mount it to a container. An example configuration for syncing the node - -```bash -## path/to/config.json -{ - "node": { - "rpcURLs": { - "http://seed6.ngd.network:10332", - "http://seed10.ngd.network:10332" - } - } -} -``` - -can be run using - -```bash -node neo-one-node --config /path/to/config.json -``` - -Individual options can also be layered on top of our configuration: - -```bash -node neo-one-node --config /path/to/config.json --environment.logger.level=trace -``` - -You can also add a `.neo-onerc` configuration file anywhere in the app directory (recommended at the root of the repo directory) to apply your configuration by default. See [rc](https://github.com/dominictarr/rc#rc) for more informatio on how NEO•ONE will find and apply the node configuration with an `rc` file. diff --git a/packages/neo-one-website/docs-old/3-node/5-heroku.md b/packages/neo-one-website/docs-old/3-node/5-heroku.md deleted file mode 100644 index abe0156619..0000000000 --- a/packages/neo-one-website/docs-old/3-node/5-heroku.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -slug: node-heroku -title: Heroku Deployment ---- - -The NEO•ONE Node can be quickly deployed on Heroku using the deployment button below. - -More information on Heroku can be found [here](https://heroku.com/). - ---- - -[[toc]] - -## Deploy! - -[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/neo-one-suite/neo-one.git) - -Upon successfully building the node-container and launching your app, you should see the node logs in your apps logs. - -## Configure - -[Configuration Reference](/docs/node-configuration) - -You can quickly apply environment variable configuration options to the node using the **Config Vars** in App >> Settings >> Config Vars. As an example we can set the log-level using a `config var` with key:value - -```bash -neo-one_telemetry__logging__level verbose -``` - -After applying the node will restart and update its configuration. - -::: warning - -Note - -Because of the environment-variable syntax `rc` expects, you must use the `neo-one___` syntax when applying a value. - -::: - -## Caveats - -Currently it is **not** possible to enable two or more `port` requiring processes simultaneously. This is because Heroku only allocates a single port to the app. By default the node's rpc server is using this port so if you would like to enable telemetry through a `config var` you will also need to disable the rpc server. - -Additionally it is not possible right now to set environment variable values for Array config options. This should be addressed soon. - -::: warning - -Note - -If you _would_ like to see metrics or enable other features that require a port, you must assign the port to `$PORT`, this is the environment variable supplied by heroku. - -::: diff --git a/packages/neo-one-website/docs-old/3-node/6-configuration.md b/packages/neo-one-website/docs-old/3-node/6-configuration.md deleted file mode 100644 index 60ffb70a5b..0000000000 --- a/packages/neo-one-website/docs-old/3-node/6-configuration.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -slug: node-configuration -title: Configuration Reference ---- - -This section will serve as a reference for the NEO•ONE Node's many configuration options. - ---- - -[[toc]] - ---- - -## Path - -```bash -... -{ - "path?": string -} -... -``` - -_defaults to the data path supplied by [env-paths](https://www.npmjs.com/package/env-paths)_ - -`path` is the path used for storing blockchain data. - -In the [local docker](/docs/node-docker#Examples) example we could store blockchain data in a location other than `/root/.local/share/neo-one`, it should be noted you will need to change the mount location as well. - -## Telemetry - -```bash -... -{ - "telemetry?": { - "logging?": { - "level": string - }, - "prometheus?": { - "prefix?": string, - "port?": number - }, - "jaeger?": { - "host?": string, - "port?": number, - "maxPacketSize?": number - } - "tracing?": { - "logLevel?": number, - "plugins?": {}, - "bufferSize?": number, - "bufferTimeout?": number - } - } -} -... -``` - -`telemetry` options control the collection and exporting of logs, metrics, and spans from the node. - -### Logging - -\*defaults to **{level: 'silent'}\*** - -Desired logging level and output path of the node logging, options are for level are: - -``` -"silent" | "fatal" | "error" | "warn" | "info" | "debug" | "trace" -``` - -### Prometheus - -_disabled by default_ - -Enables the Prometheus exporter for exporting metrics about the NEO•ONE Node. You can add an app prefix and choose a port. If no port is set prometheus will default to port `9464`. - -### Jaeger - -_disabled by default_ - -Enables the jaeger exporter for exporting spans from the NEO•ONE Node. You can optionally supply a host and port, as well as a limit on the exported packet size. See the [Jaeger homepage](https://www.jaegertracing.io/) for more. - -### Tracing - -_disabled by default_ - -Enables trace collection for the NEO•ONE Node. This must be used in tangent with `jaeger` options in order to collect AND export span information from the Node. As advanced options you can enable extra opencensus plugins, as well as limit the size and timeout of spans waiting to be exported. - -## Blockchain - -```bash -... -#basic configuration -{ - "blockchain": "main" | "test" -} -... -``` - -```bash -#advanced configuration -... -{ - "blockchain": { - "genesisBlock": string, - "governingToken": string, - "utilityToken": string, - "decrementInterval": number, - "generationAmount": number, - "fees": Record, - "registerValidatorFee": string, - "messageMagic": number, - "addressVersion": number, - "privateKeyVersion": number, - "standbyValidators": string[], - "vm": { - "storageContext": { - "v0": { - "index": number - } - } - }, - "secondsPerBlock": number, - "maxTransactionsPerBlock": number, - "memPoolSize": number - } -} -... -``` - ---- - -_defaults to `main`_ - -As a shortcut you can specify the blockchain default settings as `main` or `test` to point to the NEO mainnet/testnet. - -In most cases the above will be enough, but you have the ability to define serialized blockchain settings. See [neo-one-node-consensus-test/config](https://github.com/neo-one-suite/neo-one/blob/master/packages/neo-one-node-bin/src/__data__/configs/consensus.ts) for an example of quickly constructing a privateNet using this method. - -## RPC - -```bash -... -{ - "rpc": { - "http?": { - "port": number, - "host?": string, - "keepAliveTimeout?": number - }, - "liveHealthCheck?": { - "rpcURLs?": string[], - "offset?": number, - "timeoutMS?": number, - "checkEndpoints?": number - }, - "readyHealthCheck?": { - "rpcURLs?": string[], - "offset?": number, - "timeoutMS?": number, - "checkEndpoints?": number - } - } -} -... -``` - -`rpc` options configures the internal RPC Server of the node. See `@neo-one/node-http-rpc`. - ---- - -### HTTP - -_by default http is enabled on `localhost:8080` OR `localhost:$PORT` if you have set the `PORT` environment variable_ - -`rpc.http` is used to configure the rpc server’s host options. It is important in a kubernetes setup that `containerPort` matches `rpc.http.port`. - -`keepAliveTimeout`: if you would like your server to close after _x_ seconds without activity set a timeout here (in milliseconds). - -### Health Checks - -`liveHealthCheck` _&_ `readyHealthCheck` share the same configuration. - -- `rpcURLs`: a list of RPC URLs to compare our node to -- `offset`: the acceptable difference of blocks ahead/behind to count as `live` or `ready` -- `timeoutMS`: timeout for RPC connections -- `checkEndpoints`: the number of different endpoints to check against before passing `true`/`false`. - -## Node - -```bash -... -{ - "node": { - "externalPort?": number, - "rpcURLs?": string[], - "consensus?": { - "enabled": boolean, - "options": { - "privateKey": string, - "privateNet": boolean - } - } - } -} -... -``` - -`node` options control connections and consensus options for the NEO•ONE Node. - ---- - -`externalPort` specifies the external port of the node which it can send messages to peers on. Typically the same as `network.listenTCP`. - -`rpcURLs` specifies a list of known node RPC URLs you would like to try and connect to. A list of public mainnet hosts can be found at http://monitor.cityofzion.io/. - -`unhealthyPeerSeconds` sets how long (in seconds) to wait for a peer response before deeming it 'unhealthy'. Defaults to 300 seconds. - -`consensus` sets the consensus options for the node, requires a privateNet setup. - -- `enabled` enables consensus -- `options.privateKey` the key for the network -- `options.privateNet` true/false - -## Network - -```bash -... -{ - "network": { - "listenTCP": { - "port": number, - "host?": string - }, - "seeds?": string[], - "peerSeeds?": string[], - "externalEndpoints?": string[], - "maxConnectedPeers?": number, - "connectPeersDelayMS?": number, - "socketTimeoutMS?": number - } -} -... -``` - -`network` options can be used to control seeds, endpoints, and socketTimeout defaults. - ---- - -`listenTCP` when provided at least a port this allows other nodes to create TCP connections with this one over that port. `host` is optional and defaults to 'localhost'. - -`seeds` specifies external seeds you would like to connect to. - -`peerSeeds` specifies trusted seeds, typically ones run by yourself or on the same cluster. - -`externalEndpoints` specifies specific known external peers that you want to _ignore_ starting connections with, for instance endpoints in another cluster managed by you. - -`maxConnectedPeers` sets the maximum number of peers the node will attempt to hold a connection with at once. Defaults to 10. - -`connectPeersDelayMS` sets the amount of time (in milliseconds) to wait after requesting a peer connection before requesting another. Defaults to 5000. - -`socketTimeoutMS` sets the timeout of peer requests (in milliseconds). Defaults to 1 minute. diff --git a/packages/neo-one-website/docs-old/3-node/config.json b/packages/neo-one-website/docs-old/3-node/config.json deleted file mode 100644 index 54969a7265..0000000000 --- a/packages/neo-one-website/docs-old/3-node/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Node", - "numbered": false -} diff --git a/packages/neo-one-website/docs-old/4-contributing/0-how-to-contribute.md b/packages/neo-one-website/docs-old/4-contributing/0-how-to-contribute.md deleted file mode 100644 index ec9c271bea..0000000000 --- a/packages/neo-one-website/docs-old/4-contributing/0-how-to-contribute.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -slug: how-to-contribute -title: How to Contribute ---- - -Welcome to the NEO•ONE community! We're always looking for more contributors and are happy to have you. This document should help make the process for contributing clear and answer some questions that you may have. - -Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved. - -Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. - -This project and everyone participating in it is governed by the [Code of Conduct](/docs/code-of-conduct). By participating, you are expected to uphold this code. Please report unacceptable behavior to [contact@neo-one.io](mailto:contact@neo-one.io). - ---- - -[[toc]] - ---- - -## How Can I Contribute? - -NEO•ONE is an open source project and we love to receive contributions from our community — you! There are many ways to contribute, from writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into NEO•ONE itself. - -Please, don't use the issue tracker for support questions. The [Help](/docs/getting-started#Help) section is the best place to start for getting support. - -### Reporting Bugs - -Well-written bug reports with consistently reproducible steps are invaluable to the development of NEO•ONE. Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Before creating an issue, please perform a [search](https://github.com/neo-one-suite/neo-one/issues?q=is%3Aopen+is%3Aissue+label%3Abug) to see if the problem has already been reported. After you've determined a bug does not already exist, create an issue and fill in the template. - -### Suggesting Enhancements - -Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Please provide as much detail and context as possible. - -### How to Get Started in the NEO•ONE Repo - -- Make sure you have [Node](https://nodejs.org) >= 10.16.0 installed (We recommend the latest version). - - Linux and Mac: We recommend using [Node Version Manager](https://github.com/creationix/nvm). - - Windows: We recommend using [Chocolatey](https://chocolatey.org/). -- Install [RushJS](https://rushjs.io/) with `npm install -g @microsoft/rush`. - - We use RushJS for monorepo management. When you get started in the NEO•ONE repo you will use RushJS for nearly every task, like installing dependencies, building the packages, running tests, etc. - - For more information on RushJS, see the [docs](https://rushjs.io/pages/intro/welcome/). - - All Rush commands should be run inside the NEO•ONE repo. -- Clone the repo with `git clone https://github.com/neo-one-suite/neo-one.git`. -- Then run `rush install` to install the dependencies. -- Then run `rush build` to build the packages. Rush will perform an "incremental build", which means that it will only build packages whose source files have changed since the last successful build and the packages that depend on those packages. -- You should now be ready to start making changes to the source code. Once you're done making changes make sure to run `rush build` before running E2E tests or trying to run a bin. -- To run all the unit tests run `rush test`. To run all the E2E tests run `rush e2e`. - - There are A LOT of unit tests, which can take a few minutes to run all the way through. To only run a smaller set of tests you can specify a file or blob of tests to run with `rush test -t` or `rush e2e -t`. - - For example, if you wanted to only run the unit tests in `neo-one-client-common` you would run `rush test -t packages/neo-one-client-common/src/__tests__/**/*` -- If you want to test your changes with the NEO•ONE CLI run `rush build`. Then, to start the CLI you'd run `node packages/neo-one-cli/bin/neo-one.js` from inside the NEO•ONE repository. You will then be running the new NEO•ONE CLI with your changes. From there you can see your new code directly in action. -- To see all the available RushJS commands run `rush --help`. - -### Your First Code Contribution - -Unsure where to begin contributing to NEO•ONE? Here are some great ways to get started: - -- Chat with us on [Discord](https://discord.gg/S86PqDE) about ways to contribute! -- Documentation (like the text you are reading now) can always use improvement! All pages on this website include an edit button which you can click to modify the documentation. -- Adding test coverage is a great way to get familiar with the codebase. -- Find an existing issue with the [help wanted and good first issue](https://github.com/neo-one-suite/neo-one/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Ahelp%20wanted+label%3Agood%20first%20issue) labels. - -Once you've had your first pull request approved and merged, find existing issues marked with [help wanted](https://github.com/neo-one-suite/neo-one/issues?utf8=%E2%9C%93&q=is%3Aopen+label%3Ahelp%20wanted) labels to continue contributing or suggest an enhancement. Respond on the issue thread expressing interest in working on it. This helps other people know that the issue is active, and hopefully prevents duplicated efforts. - ---- - -## Pull Requests - -- Follow the process outlined in [GitHub Standard Fork & Pull Request Workflow](https://gist.github.com/Chaser324/ce0505fbed06b947d962) when submitting a pull request. -- Fill in the pull request template. -- Pre-commit hooks will run basic checks automatically. -- Pull requests should typically be accompanied with tests. Your reviewers will request tests when appropriate if they are missing. - ---- - -## License - -By contributing to NEO•ONE, you agree that your contributions will be licensed under its MIT license. diff --git a/packages/neo-one-website/docs-old/4-contributing/1-codebase-overview.md b/packages/neo-one-website/docs-old/4-contributing/1-codebase-overview.md deleted file mode 100644 index 02f6174339..0000000000 --- a/packages/neo-one-website/docs-old/4-contributing/1-codebase-overview.md +++ /dev/null @@ -1,272 +0,0 @@ ---- -slug: codebase-overview -title: Codebase Overview ---- - -NEO•ONE is a very large project, which is organized into 50+ interdependent packages. Below is a breakdown -of what each package is used for, grouped by functionality. - ---- - -[[toc]] - ---- - -## Client - -### neo-one-client - -Exports nearly everything from `neo-one-client-common` and `neo-one-client-core`, plus `DeveloperTools` from `neo-one-developer-tools`. - -### neo-one-client-common - -One of the core client packages, which provides APIs for cryptography, commonly used client functions, reading binary input, building scripts, and more. - -### neo-one-client-core - -The core client package, which exports the NEO•ONE Client, which is used to construct and send transactions, read accounts, hold keys, read the blockchain, and much more. - -### neo-one-client-full - -Exports nearly everything from `neo-one-client` and `neo-one-client-full-core`. - -### neo-one-client-full-common - -Exports common models. - -### neo-one-client-full-core - -Contains an extension of the Client in `neo-one-client-core` which provides extra APIs and functionality, plus the ReadClient, and more. - -### neo-one-client-switch - -Provides NEO•ONE Client functionality that switches between NodeJS and browser environments. - -## Node - -### neo-one-node - -Contains the `FullNode` class which is used by the NEO•ONE CLI, `neo-one-node-bin`, and for testing purposes. - -### neo-one-node-bin - -Contains the `bin` for staring the NEO•ONE node. - -### neo-one-node-blockchain - -Primarily contains the `Blockchain` class which handles nearly every blockchain function for the node. - -### neo-one-node-browser - -Creates the full NEO•ONE node used in the browser, especially for the NEO•ONE website courses. - -### neo-one-node-browser-worker - -The web worker wrapper for the NEO•ONE node used in the browser. - -### neo-one-node-concensus - -Handles concensus for the node. - -### neo-one-node-core - -Contains all the objects for Accounts, Blocks, Transactions, Contracts, Headers, etc. used in the node and other packages. - -### neo-one-node-http-rpc - -Creates the actual HTTP server used by the node for relaying RPC calls. - -### neo-one-node-neo-settings - -Handles the node settings, like creating the genesis block, defining the governing token, and setting other key blockchain constants. - -### neo-one-node-network - -Contains the functionality for relaying information between the NEO•ONE node and other nodes in the network. - -### neo-one-node-offline - -Handles offline operations for the node, like dumping and loading chainfile data. - -### neo-one-node-protocol - -Handles the protocol for connecting to other nodes in the network. - -### neo-one-node-rpc-handler - -Contains the function which creates the RPC handlers for the node. These handlers are what are called by the node when it receives RPC requests. - -### neo-one-node-storage-cache - -Handles storage data caching for the node. - -### neo-one-node-storage-common - -Contains common functions used by node storage. - -### neo-one-node-storage-levelup - -Creates the storage and the storage APIs used by the node to store and access blockchain data. - -### neo-one-node-tools - -Primarily provides the entrypoint for restoring a NEO•ONE node from blockchain data, like in a chainfile. - -### neo-one-node-vm - -Contains the NEO•ONE implementation of the NeoVM, used in the NEO•ONE node and used for testing the compiler. - -### neo-one-http - -Contains very basic Koa HTTP server utils. - -### neo-one-http-context - -Contains very basic server utils, plus common functions and constants. - -## CLI - -### neo-one-cli - -This is the main entrypoint for the NEO•ONE CLI code. It handles all NEO•ONE CLI commands. - -### neo-one-cli-common - -Handles more CLI functionality, like configuration, setting up wallets, setting up a NEO•ONE Client, etc. - -### neo-one-cli-common-node - -Contains more CLI features, like configuration and network setup. - -## Compiler - -### neo-one-smart-contract - -Exports declaration files that define custom types used in a NEO•ONE smart contract. - -### neo-one-smart-contract-codegen - -Generates helpers for invoking smart contracts, and generates other code for creating dApps around smart contracts. - -### neo-one-smart-contract-compiler - -The largest package in NEO•ONE. Contains the entire smart contract compiler, which creates the actual compiled NeoVM bytecode. - -### neo-one-smart-contract-compiler-node - -Creates the environment for compiling smart contracts, which is then used in the CLI and other packages. - -### neo-one-smart-contract-lib - -Defines NEP5 tokens and ICOs. - -### neo-one-smart-contract-test - -Creates the environment for testing smart contracts. - -### neo-one-smart-contract-test-browser - -Creates the environment for testing smart contracts in the browser. - -### neo-one-smart-contract-test-common - -Runs smart contract unit tests. - -### neo-one-smart-contract-typescript-plugin - -Creates a plugin for the NEO•ONE smart contract compiler. - -## Website - -### neo-one-react - -Primarily creates and exports a `FromStream` React component for subscribing to `Observables` in React. - -### neo-one-react-common - -Creates additional React components that are used by the NEO•ONE website and exports everything from `neo-one-react-core`. - -### neo-one-react-core - -Creates all the base React components that are used by the NEO•ONE website and other React components. - -### neo-one-website - -Contains the entire NEO•ONE website. - -### neo-one-worker - -Contains helpers for creating and connecting web workers, especially for the NEO•ONE website. - -### neo-one-local-browser - -Handles a lot of the setup and execution of the courses on the NEO•ONE website, like loading files into a browser-implemented -DB, compiling smart contracts, deploying contracts, testing contracts, etc. - -### neo-one-local-browser-worker - -A web worker wrapper for `neo-one-local-browser`. - -### neo-one-local-singleton - -Contains functions that are used in the browser for the NEO•ONE courses. - -### neo-one-editor - -Contains the code for the code editor used in the NEO•ONE website. - -### neo-one-editor-server - -Contains the code for the code editor server used in the NEO•ONE website. - -## Build - -### neo-one-build-common - -Common build modules. - -### neo-one-build-tests - -Environment setup for running Jest unit and end-to-end tests. - -### neo-one-build-tools - -Contains all the build tools for checking, cleaning, formatting, preparing, and building NEO•ONE packages. - -### neo-one-build-tools-web - -Contains all the webpack compilers and build configurations, primarily for the NEO•ONE website. - -## Other - -### neo-one-logger - -Handles almost all the logging for NEO•ONE packages. - -### neo-one-logger-config - -Handles configuration for `neo-one-logger`. - -### neo-one-developer-tools - -Provides the interface for controlling a private development network. - -### neo-one-developer-tools-frame - -Creates the developer tools iframe for controlling a private network. - -### neo-one-ts-utils - -Primarily exports TypeScript compiler API helper functions for use in build tools, the compiler, and more. - -### neo-one-typescript-concatenator - -Handles the concatenation of multiple TypeScript files into one file for the TypeScript compiler. - -### neo-one-utils - -Contains various helper functions, utilities, and constants that are used throughout NEO•ONE. - -### neo-one-utils-node - -Contains various helper functions, utilities, and constants that are used primarily in the node. diff --git a/packages/neo-one-website/docs-old/4-contributing/2-smart-contract-compiler.md b/packages/neo-one-website/docs-old/4-contributing/2-smart-contract-compiler.md deleted file mode 100644 index 170dac5dbf..0000000000 --- a/packages/neo-one-website/docs-old/4-contributing/2-smart-contract-compiler.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -slug: smart-contract-compiler -title: Smart Contract Compiler ---- - -## How Can I Add New Features or Fix Bugs in the Smart Contract Compiler? - -### Basics of the Smart Contract Compiler - -The NEO•ONE Smart Contract Compiler is by far the _largest_ NEO•ONE package. The compiler takes in (almost) regular -TypeScript code and compiles it to [NeoVM](https://docs.neo.org/docs/en-us/basic/technology/neovm.html) bytecode, which can -then be deployed to the Neo blockchain and run on the NeoVM. NEO•ONE uses the TypeScript compiler API to parse the TypeScript code -into a tree of "nodes" with information about each node. Our compiler then "visits" each node and begins to output specific -bytecode for the VM instructions that are needed in order to execute the logic that is specified by the TypeScript code. -The bytecode outputted by the compiler corresponds to human-readable opcodes that each correspond to an action that the -NeoVM will perform. These actions are the manipulation of data by the NeoVM that will ultimately translate to changes to the -state of the Neo blockchain. - -### Where to Look in the Code - -Now that you have a _very_ basic understanding of how the NEO•ONE compiler works, you can start digging into the `neo-one-smart-contract-compiler` -package. Most likely you'll be looking in `neo-one-smart-contract-compiler/compiler/` (where `` is one of `constants`, `declaration`, `expression`, `helper`, `scope`, `statement`) -for the specific syntax that is broken or where you want to add a feature. For example, if you want to change how we compile the `==` token, you would -look for `EqualsEqualsEqualsHelper.ts` in `neo-one-smart-contract-compiler/compiler/helper/relational/EqualsEqualsHelper.ts`. In there you'll see -how this helper will "emit" different opcodes, syscalls, and other helpers to manipulate the Evaluation Stack. The comment line above each emit shows a -representation of the Evaluation Stack _after_ that bytecode is evaluated. - -### Write Unit Tests for What You're Working On - -Once you have an understanding of what helpers or syntax compilers you need to change in order to make your compiler change, the best way to begin is to write -a unit test that you will run to test your change. You'll see that nearly every helper and syntax compiler has a corresponding set of unit tests in `neo-one-smart-contract-compiler/src/__tests__`. -For example, the `IfStatementCompiler.ts` has a set of unit tests in `IfStatementCompiler.test.ts`. In there you'll see that we typically use the built in `assertEqual` method to -test if values are what we expect them to be. You'll also see that we have helpers, like the `helpers.executeString()` helper, that make it easy to compile a string and test for certain behavior. - -Here is an example unit test you would write to test your changes: - -```ts -import { helpers } from '../../../__data__'; - -describe('MyNewCompiler', () => { - test.only('simple test', async () => { - await helpers.executeString(` - if (!true) { - throw 'Failure'; - } - - const x = '10'; - assertEqual(x, '10'); - `); - }); -}); -``` - -### Start Hacking - -Once you've created a unit test that either recreates the bug you're trying to fix, or tests for the expected behavior of your new feature, you can start to make changes -to the compiler's source code and run your unit test. If you want to add logging (ie. `console.log`) to the source code to get more information you can, just make sure -to change the console settings in `neo-one-build-tests/environments/test/jestSetup.js`. From there you should make sure to only run one unit test at a time -so that you're only getting logs from the compilation of that one unit test. This will make it easier to learn what the compiler is doing when compiling a specific string. -To run a specific unit test, rather than all unit tests, run `rush test -t `. - -And that's it! Once you have this workflow setup you can hack away at the compiler code and run the unit test to test your changes, get logs, etc. diff --git a/packages/neo-one-website/docs-old/4-contributing/3-code-of-conduct.md b/packages/neo-one-website/docs-old/4-contributing/3-code-of-conduct.md deleted file mode 100644 index 2cbf969889..0000000000 --- a/packages/neo-one-website/docs-old/4-contributing/3-code-of-conduct.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -slug: code-of-conduct -title: Code of Conduct ---- - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -education, socio-economic status, nationality, personal appearance, race, -religion, or sexual identity and orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or - advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at [contact@neo-one.io](mailto:contact@neo-one.io). All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html diff --git a/packages/neo-one-website/docs-old/4-contributing/config.json b/packages/neo-one-website/docs-old/4-contributing/config.json deleted file mode 100644 index 0f789a51e2..0000000000 --- a/packages/neo-one-website/docs-old/4-contributing/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Contributing", - "numbered": false -} diff --git a/packages/neo-one-website/docs/0-installation/0-quick-start.md b/packages/neo-one-website/docs/0-installation/0-quick-start.md index e1130208d4..5ad5fbd1f1 100644 --- a/packages/neo-one-website/docs/0-installation/0-quick-start.md +++ b/packages/neo-one-website/docs/0-installation/0-quick-start.md @@ -31,41 +31,61 @@ Tip ## Installations -1. Install [NodeJS](https://nodejs.org) >= 10.16.0 (Latest version recommended) +1. Install [NodeJS](https://nodejs.org) >= 10.16.0 (We recommend using v10.16.0) - Linux and Mac: [Node Version Manager](https://github.com/creationix/nvm). (`recommended`) - Windows: We recommend using [Chocolatey](https://chocolatey.org/). (`recommended`) -2. Follow the [installation instructions for Create React App](https://reactjs.org/docs/create-a-new-react-app.html#create-react-app) to make a new project. +2. Install [C# .NET](https://docs.microsoft.com/en-us/dotnet/) version 3.1.401 +3. Add a `global.json` file to the root of your project repo with this JSON: - - Be sure to invoke Create React App with the `--template typescript` in order to enable TypeScript support: `npx create-react-app token --template typescript` +```json +{ + "sdk": { + "version": "3.1.401" + } +} +``` -3. Install NEO•ONE using either [yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/) +This tells your local C# .NET runtime to use version 3.1.401 in this repo, even if you have newer versions installed on your machine. -```bash -yarn add @neo-one/suite -``` +4. Follow the [installation instructions for Create React App](https://reactjs.org/docs/create-a-new-react-app.html#create-react-app) to make a new project. -```bash -npm install @neo-one/suite -``` + - Be sure to invoke Create React App with the `--template typescript` in order to enable TypeScript support: `npx create-react-app token --template typescript` -Alternatively, install the individual packages `@neo-one/suite` wraps for you: +5. Install NEO•ONE using either [yarn](https://yarnpkg.com/) or [npm](https://www.npmjs.com/) ```bash -yarn add @neo-one/cli @neo-one/client @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +yarn add @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` ```bash -npm install @neo-one/cli @neo-one/client @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +npm install @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` -4. Run `yarn neo-one init` or `npx neo-one init` +6. Run `yarn neo-one init` or `npx neo-one init` The command above generates a sample `HelloWorld.ts` smart contract, a sample test for the contract `HelloWorld.test.ts`, a config file `.neo-one.config.ts`, and a `neo-one` folder with important modules. --- +## Troubleshooting + +You may or may not run into environment problems when using the CLI, trying to test your smart contract, or other NEO•ONE functions that use the NEO•ONE node. The NEO•ONE node now uses the C# NeoVM instead of our own implementation of the NeoVM in TypeScript, which means that NEO•ONE controls C# code through some complicated mechanisms. If you run into problems with running a node (such as when running `neo-one init` or `neo-one build`) then try these steps: + +- Add these environment variables to your shell environment: + - `EDGE_USE_CORECLR=1` + - `EDGE_APP_ROOT=/node_modules/@neo-one/node-vm/lib/Debug/netcoreapp3.0` +- Install `pkgconfig` on macOS with Homebrew: `brew install pkgconfig` + - Then add this environment variable: `PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig` + - You then need to re-install your node modules by deleting the `node_modules` folder and then running `npm install` again +- Try running the NEO•ONE CLI command using `sudo`, such as: `sudo npx neo-one init` +- If problems persist then please reach out to us on [Discord](https://discord.gg/S86PqDE) + +To see a demonstration of environment setup go to our YouTube channel for helpful videos: https://www.youtube.com/channel/UCya5J1Tt2h-kX-I3a7LOvtw + +--- + ## A Contract in NEO•ONE Every NEO•ONE smart contract starts with a TypeScript source file that exports a single [class](https://www.typescriptlang.org/docs/handbook/classes.html) extending `SmartContract`. @@ -77,7 +97,6 @@ import { SmartContract } from '@neo-one/smart-contract'; export class Token extends SmartContract { public readonly mutableSupply: Fixed<8> = 0; - // @constant public get totalSupply(): Fixed<8> { return this.mutable; @@ -234,15 +253,13 @@ export default ({ token, ico, escrow }: MigrationContracts, _network: string) => Note -For more details on deployment specifics and migration files, check out the [Deployment](/docs/deployment) page. +Deployment has not been thoroughly tested yet for N3. It _should_ work, but there may be bugs, so be aware and feel free to bring up issues and ask questions in our [Discord](https://discord.gg/S86PqDE) server. For more details on deployment specifics and migration files, check out the [Deployment](/docs/deployment) page. ::: ### Get Test coins -You can get test coins automatically from https://neowish.ngd.network/ - -Limited to 1000 NEO and 1000 GAS per day. +You can get test coins automatically from https://neowish.ngd.network/neo3/#/ If you need more than that. You must apply through Neo website. Please follow the instructions here: https://docs.neo.org/docs/en-us/network/testnet.html#applying-for-test-coin-from-neo-website @@ -279,5 +296,4 @@ We **HIGHLY** recommend deploying to both a local private network and the Neo Te ## Explore with NEO Tracker -If your deployment to the TestNet was successful you should be able to find your contract at https://testnet.neotracker.io/browse/contract/1. - +NEO Tracker doesn't currently support N3, so you will have to use another explorer to see your deployed contracts. diff --git a/packages/neo-one-website/docs/0-installation/1-getting-started.md b/packages/neo-one-website/docs/0-installation/1-getting-started.md index aeed1587a2..6cc203b48a 100644 --- a/packages/neo-one-website/docs/0-installation/1-getting-started.md +++ b/packages/neo-one-website/docs/0-installation/1-getting-started.md @@ -19,28 +19,16 @@ NEO•ONE has been designed as a full end-to-end toolkit for building NEO dapps. The links in this section will help you get started. -### Courses - -If you're interested in playing around with NEO•ONE or you prefer to **learn by doing**, check out [NEO•ONE Courses](/course). As you work through the first two lessons you'll experience the entire development lifecycle of a dapp by deploying a fully functioning ICO, from the smart contract that powers it all to the UI that enables participation. All directly from your browser - no environment setup required. - ### Tutorial If you'd prefer to use your own editor, you can work through the [NEO•ONE Tutorial](/tutorial). The tutorial covers roughly the same content as the first course and by the end of it you'll be ready to start building your own unique dapp. -### Playground - -Setup the [NEO•ONE Playground](/docs/playground) repository to get a feel for NEO•ONE in a real-world setting. Try modifying the smart contracts, adding to the tests or playing with the UI. Once you're comfortable, you can even try adding your own dapp! - --- ## Learn NEO•ONE NEO•ONE covers the entire development lifecycle of a dapp, so it's best to learn it one step at a time. -### First Examples - -The [NEO•ONE Homepage](/) contains a full editor with a simplified token smart contract example and tests. Even if you don't know anything about building dapps, check it out to see what's possible. - ### TypeScript Resources NEO•ONE is written in TypeScript and the documentation assumes some familiarity with TypeScript. If you've never used TypeScript before, or it's been a while, keep the [TypeScript documentation](https://www.typescriptlang.org/docs/handbook/basic-types.html) handy while working through the NEO•ONE documentation. diff --git a/packages/neo-one-website/docs/0-installation/2-environment-setup.md b/packages/neo-one-website/docs/0-installation/2-environment-setup.md index 7c75068e4f..f17118c6d2 100644 --- a/packages/neo-one-website/docs/0-installation/2-environment-setup.md +++ b/packages/neo-one-website/docs/0-installation/2-environment-setup.md @@ -18,6 +18,7 @@ This page describes how to setup NEO•ONE using `yarn` or `npm`. - [Node](https://nodejs.org) >= 10.16.0 (We recommend the latest version) - Linux and Mac: We recommend using [Node Version Manager](https://github.com/creationix/nvm). - Windows: We recommend using [Chocolatey](https://chocolatey.org/). +- [C# .NET](https://docs.microsoft.com/en-us/dotnet/) version 3.1.401 --- @@ -29,6 +30,31 @@ This page describes how to setup NEO•ONE using `yarn` or `npm`. - [Angular CLI](https://cli.angular.io/) - Generates an [Angular](https://angular.io/) starter app. - [Vue CLI](https://cli.vuejs.org/) - Generate a [Vue](https://vuejs.org/) starter app. +**Make sure you add** this `global.json` file to the root of your project repo: + +```json +{ + "sdk": { + "version": "3.1.401" + } +} +``` + +This tells your local C# .NET runtime to use version 3.1.401 in this repo, even if you have newer versions installed on your machine. + +**You may need to also add environment variables** to get the NEO•ONE node working. The NEO•ONE node now uses the C# NeoVM instead of our own implementation of the NeoVM in TypeScript, which means that NEO•ONE controls C# code through some complicated mechanisms. If you run into problems with running a node (such as when running `neo-one init` or `neo-one build`) then try these steps: + +- Add these environment variables to your shell environment: + - `EDGE_USE_CORECLR=1` + - `EDGE_APP_ROOT=/node_modules/@neo-one/node-vm/lib/Debug/netcoreapp3.0` +- Install `pkgconfig` on macOS with Homebrew: `brew install pkgconfig` + - Then add this environment variable: `PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig` + - You then need to re-install your node modules by deleting the `node_modules` folder and then running `npm install` again +- Try running the NEO•ONE CLI command using `sudo`, such as: `sudo npx neo-one init` +- If problems persist then please reach out to us on [Discord](https://discord.gg/S86PqDE) + +To see a demonstration of environment setup go to our YouTube channel for helpful videos: https://www.youtube.com/channel/UCya5J1Tt2h-kX-I3a7LOvtw + **Once you have a project setup**, the next step is to add NEO•ONE to it. NEO•ONE is organized into multiple individual packages. Use as much or as little as you like. Each package may be installed using either [yarn](https://yarnpkg.com/) (`yarn add `) or [npm](https://www.npmjs.com/) (`npm install `). Each package has the form `@neo-one/`, for example, `@neo-one/client`. Make sure to install the correct versions of these packages. If you are working on Neo3 then make sure you are installing NEO•ONE packages at version 3.0.0 or higher. @@ -36,13 +62,13 @@ Make sure to install the correct versions of these packages. If you are working Install all the neo-one packages with yarn by running: ```bash -yarn add @neo-one/client @neo-one/cli @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +yarn add @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` Install all the neo-one packages with npm by running: ```bash -npm install @neo-one/client @neo-one/cli @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +npm install @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` and then follow the [main guide](/docs/hello-world) or the [tutorial](/tutorial). By the end of it you'll know which features of NEO•ONE you're using and which packages to keep. @@ -67,7 +93,7 @@ In addition to the above, if you're developing TypeScript smart contracts using ### Update ```bash -#npm update @neo-one/cli +# npm update @neo-one/cli yarn upgrade @neo-one/cli ``` diff --git a/packages/neo-one-website/docs/0-installation/5-contract-mixins.md b/packages/neo-one-website/docs/0-installation/4-contract-mixins.md similarity index 90% rename from packages/neo-one-website/docs/0-installation/5-contract-mixins.md rename to packages/neo-one-website/docs/0-installation/4-contract-mixins.md index be0198793e..dbf456c882 100644 --- a/packages/neo-one-website/docs/0-installation/5-contract-mixins.md +++ b/packages/neo-one-website/docs/0-installation/4-contract-mixins.md @@ -18,11 +18,11 @@ This guide will walk you through how to use a mixin. Install the following packages if you have not done so: ```bash -yarn add @neo-one/client @neo-one/cli @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +yarn add @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` ```bash -npm install @neo-one/client @neo-one/cli @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +npm install @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` ::: warning diff --git a/packages/neo-one-website/docs/0-installation/4-playground.md b/packages/neo-one-website/docs/0-installation/4-playground.md deleted file mode 100644 index 28f46c17c3..0000000000 --- a/packages/neo-one-website/docs/0-installation/4-playground.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -slug: playground -title: Playground ---- - -The NEO•ONE Playground showcases what's possible with NEO•ONE. - -This guide will walk you through getting started with the [NEO•ONE Playground](https://github.com/neo-one-suite/neo-one-playground). - ---- - -[[toc]] - ---- - -## Requirements - -- [Node](https://nodejs.org) >= 10s.16.0 (We recommend the latest version) -- a package manager: [yarn](https://yarnpkg.com/) **OR** npm (distributed with Node) - ---- - -## Installation - -```bash -git clone https://github.com/neo-one-suite/neo-one-playground.git -cd neo-one-playground -# npm install -yarn install -``` - ---- - -## Compile - -```bash -# npx neo-one build -yarn neo-one build -``` - -This will start up a local network, compile the smart contracts located in the `neo-one/contracts` directory and publish them to your local network. Add `--watch` to listen for changes to the smart contracts and trigger automatic recompilation and deployment. - ---- - -## Start the Playground - -```bash -# npm start -yarn start -``` - -This will open a browser window with the playground. Modify the files in the `src` directory to get a feel for using the NEO•ONE client APIs. - ---- - -## Run the tests - -```bash -# npm test -yarn test -``` - -Smart contract tests in the playground are written in Jest and are located in the `src/__tests__` directory. Play around with them to see how easy it is to test smart contracts! diff --git a/packages/neo-one-website/docs/1-main-concepts/00-hello-world.md b/packages/neo-one-website/docs/1-main-concepts/00-hello-world.md index d6ce4aa70d..f63e833c23 100644 --- a/packages/neo-one-website/docs/1-main-concepts/00-hello-world.md +++ b/packages/neo-one-website/docs/1-main-concepts/00-hello-world.md @@ -25,7 +25,7 @@ In this guide, we will work through creating a dapp with NEO•ONE starting from Tip -This guide is designed for people who prefer **learning concepts step by step**. If instead you'd like to learn by doing, check out [NEO•ONE Courses](/course) or the [tutorial](/tutorial). This guide can also serve as a complementary resource to the courses and tutorial. +This guide is designed for people who prefer **learning concepts step by step**. If instead you'd like to learn by doing, check out the [tutorial](/tutorial). This guide can also serve as a complementary resource to the tutorial. ::: diff --git a/packages/neo-one-website/docs/1-main-concepts/01-blockchain-basics.md b/packages/neo-one-website/docs/1-main-concepts/01-blockchain-basics.md index 942e82b71a..e79e85a5d3 100644 --- a/packages/neo-one-website/docs/1-main-concepts/01-blockchain-basics.md +++ b/packages/neo-one-website/docs/1-main-concepts/01-blockchain-basics.md @@ -81,14 +81,10 @@ Delegated Proof of Stake (dPOS) works in a similar way to PoS, however instead o ## NEO Specifics -NEO's blockchain data structure is very similar to other blockchains and the general outline we gave above. Like Bitcoin, NEO uses the UTXO model for its native assets, NEO and GAS. Like Ethereum, NEO is a full smart contract platform with its own virtual machine. +NEO's blockchain data structure is very similar to other blockchains and the general outline we gave above. NEO uses smart contract storage to keep track of native assets NEO and GAS. Like Ethereum, NEO is a full smart contract platform with its own virtual machine. -One differentiating factor to be aware of is that NEO has several different types of transactions that can be included in a block; we'll list the most important ones below: +NEO's transactions all contains scripts which are used to invoke smart contracts, including "native" contracts which control voting, native assets NEO and GAS, and other blockchain APIs. -1. `ContractTransaction` - Used for transferring native assets. May only contain inputs and outputs. -2. `InvocationTransaction` - Used for invoking smart contracts. May contain inputs and outputs. -3. `ClaimTransaction` - Used for claiming accrued GAS - -Take a look at the [@neo-one/client](/reference/@neo-one/client) reference for more details on the specific properties stored on each transaction type. Note the final transaction in that list, the `ClaimTransaction`, refers to claiming GAS. GAS is produced every block and allocated to every NEO holder in proportion to their holdings. NEO holders claim their GAS by submitting a `ClaimTransaction` to the network. GAS is used to "fuel" the network; it's used primarily for transaction fees and is also meant as the primary currency. NEO, on the other hand, is meant to represent ownership of the network and is used only for voting and generating GAS. +GAS is produced every block and allocated to every NEO holder in proportion to their holdings. GAS is used to "fuel" the network; it's used primarily for transaction fees and is also meant as the primary currency. NEO, on the other hand, is meant to represent ownership of the network and is used for voting and generating GAS. NEO uses a form of dPOS called Delegated Byzantine Fault Tolerance (dBFT). While we won't go into detail on the algorithm, the key differentiator of dBFT is that it results in one block finality. Once a block has been propagated on the network it cannot be reversed. Contrast this with most blockchain consensus algorithms which can have anywhere from 6 blocks to 40 or more block finality. NEO holders vote in consensus nodes which participate in producing new blocks via dBFT. diff --git a/packages/neo-one-website/docs/1-main-concepts/03-standard-library.md b/packages/neo-one-website/docs/1-main-concepts/03-standard-library.md index 50bec9be16..8bb8c6baa2 100644 --- a/packages/neo-one-website/docs/1-main-concepts/03-standard-library.md +++ b/packages/neo-one-website/docs/1-main-concepts/03-standard-library.md @@ -23,7 +23,7 @@ The standard library includes several specialized value types which are defined - `Hash256` - a `Buffer` that represents a NEO 256 bit hash, most commonly used for asset ids like `NEO` or `GAS` asset ids. - `PublicKey` - a `Buffer` that represents a public key. -Each of the value types can be created from a string literal using the `from` [static method](https://www.typescriptlang.org/docs/handbook/classes.html#static-properties), for example, `Address.from('APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR')`. `Hash256` also contains static properties for the `NEO` and `GAS` `Hash256` values. +Each of the value types can be created from a string literal using the `from` [static method](https://www.typescriptlang.org/docs/handbook/classes.html#static-properties), for example, `Address.from('APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR')`. `Address` also contains static properties for the `NEO` and `GAS` `Address` values. The `Address` type has a commonly used static method, `isCaller`, which is used to check that the passed `Address` directly called and approved the current method invocation. @@ -53,7 +53,7 @@ The `Blockchain` value contains several properties pertaining to the current sta - `Blockchain.currentBlockTime` - the timestamp of the `Block` that this `Transaction` will be included in. - `Blockchain.currentHeight` - index of the last `Block` persisted to the blockchain. -- `Blockchain.currentTransaction` - the current `InvocationTransaction`. +- `Blockchain.currentTransaction` - the current `Transaction`. - `Blockchain.currentCallerContract` - the `Address` of the smart contract that directly invoked this contract. May be `undefined` if the current invocation was not from another smart contract. --- diff --git a/packages/neo-one-website/docs/1-main-concepts/05-methods.md b/packages/neo-one-website/docs/1-main-concepts/05-methods.md index 05ce14a9bc..99fcbcb745 100644 --- a/packages/neo-one-website/docs/1-main-concepts/05-methods.md +++ b/packages/neo-one-website/docs/1-main-concepts/05-methods.md @@ -38,7 +38,12 @@ Public instance methods come in several flavors but they effectively break down 1. Normal instance methods. These have no restrictions and work identically to instance methods in normal TypeScript. 2. Constant instance methods. Designated with the `@constant` decorator, these methods may not modify smart contract properties. These methods can be called by any contract. Even if the contract's manifest specifies trusted contracts, trusted groups, and permissions, any contract will be able to call a method marked as `@constant`. -3. Native asset instance methods. Designated with the `@receive`, `@sendUnsafe`, `@send` and `@claim` decorators. Read more about these in the [Native Assets](/docs/native-assets) advanced guide. + +::: warning + +Due to recent changes in the NeoVM the `@constant` decorator may cause errors if a method happens to use certain APIs that will cause it to actually use contract storage. We are working on removing this flaw, but in the meantime if you get an uncertain error from calling a method marked `@constant` and aren't sure what is going on try to remove the `@constant` decorator and call again. + +::: Public instance methods define the API of the smart contract. In the following example we have two methods. One is a constant method since it's decorated with `@constant`. The other is a normal instance method which modifies the smart contract property `mutableClosing`. diff --git a/packages/neo-one-website/docs/1-main-concepts/08-client-apis.md b/packages/neo-one-website/docs/1-main-concepts/08-client-apis.md index 79196f7afd..f4bb0c37b8 100644 --- a/packages/neo-one-website/docs/1-main-concepts/08-client-apis.md +++ b/packages/neo-one-website/docs/1-main-concepts/08-client-apis.md @@ -37,10 +37,10 @@ The `Client` class also contains two methods for creating transactions. class Client { public async transfer( amount: BigNumber, - asset: Hash256String, + asset: AddressString, to: AddressString, options?: TransactionOptions, - ): Promise>; + ): Promise; public async transfer(transfers: readonly Transfer[], options?: TransactionOptions): Promise; public async claim(optionsIn?: TransactionOptions): Promise; @@ -69,17 +69,29 @@ interface TransactionOptions { */ attributes?: readonly Attribute[]; /** - * An optional network fee to include with the transaction. + * A maximum network fee to include with the transaction. Note that this is a maximum, the client APIs will automatically calculate and add a system fee to the transaction up to the value specified here. + * + * Leaving `maxNetworkFee` `undefined` is equivalent to `new BigNumber(0)`, i.e. no network fee. + * + * A `maxNetworkFee` of `-1`, i.e. `new BigNumber(-1)` indicates no limit on the fee. This is typically used only during development. + * + * Network fee is a required fee that depends on the size of the transaction. */ - networkFee?: BigNumber; + maxNetworkFee?: BigNumber; /** * A maximum system fee to include with the transaction. Note that this is a maximum, the client APIs will automatically calculate and add a system fee to the transaction up to the value specified here. * - * Leaving `systemFee` `undefined` is equivalent to `new BigNumber(0)`, i.e. no system fee. + * Leaving `maxSystemFee` `undefined` is equivalent to `new BigNumber(0)`, i.e. no system fee. + * + * A `maxSystemFee` of `-1`, i.e. `new BigNumber(-1)` indicates no limit on the fee. This is typically used only during development. + */ + maxSystemFee?: BigNumber; + /** + * The maximum number of blocks from the current block this transaction should stay valid until. Defaults to the network's `maxValidBlockIncrement` minus 1. * - * A `systemFee` of `-1`, i.e. `new BigNumber(-1)` indicates no limit on the fee. This is typically used only during development. + * Useful for when there is high traffic on the network and automatic re-sending of transactions takes place but you want more control. */ - systemFee?: BigNumber; + validBlockCount?: number; } ``` @@ -87,12 +99,12 @@ Putting this all together, if we wanted to transfer funds to another account, bu ```typescript const account = await client.getAccount(otherAccountID); -if (account.balances[Hash256.NEO] === undefined) { - await client.transfer.confirmed(new BigNumber(10), Hash256.NEO, otherAccountID.address); +if (account.balances[Hash160.NEO] === undefined) { + await client.transfer.confirmed(new BigNumber(10), Hash160.NEO, otherAccountID.address); } ``` -We'll learn more about the `confirmed` property in the next chapter. Also take note of the `Hash256.NEO` property, which works just like the `Hash256.NEO` property in smart contracts and can be imported directly from `@neo-one/client`. +We'll learn more about the `confirmed` property in the next chapter. Also take note of the `Hash160.NEO` property, which works just like the `Hash160.NEO` property in smart contracts and can be imported directly from `@neo-one/client`. --- @@ -110,8 +122,8 @@ The output directory for generated files is configurable. You can also change th For each contract, the toolchain will emit 3 files: -- `src/neo-one//abi.ts` - Contains the ABI that generates the client smart contract APIs at runtime that we'll discuss in the next chapter. -- `src/neo-one//contract.ts` - Contains the smart contract definition, which contains the ABI, the source maps for the contract and a mapping from network name to deployed address for the smart contract. Initially the network mapping will only contain the `local` network which represents your local development network. Once you deploy your smart contract to the TestNet or MainNet, it will also contain deployed contract addresses for those networks. The client APIs automatically choose which address to work with based on the network of the user account that is initiating the request. This file also contains a helper function for creating the smart contract APIs given a `Client`. +- `src/neo-one//manifest.ts` - Contains the Manifest that generates the client smart contract APIs at runtime that we'll discuss in the next chapter. +- `src/neo-one//contract.ts` - Contains the smart contract definition, which contains the Manifest, the source maps for the contract and a mapping from network name to deployed address for the smart contract. Initially the network mapping will only contain the `local` network which represents your local development network. Once you deploy your smart contract to the TestNet or MainNet, it will also contain deployed contract addresses for those networks. The client APIs automatically choose which address to work with based on the network of the user account that is initiating the request. This file also contains a helper function for creating the smart contract APIs given a `Client`. - `src/neo-one//types.ts` - Contains the TypeScript type definitions for the smart contract client APIs. 5 files will also be emitted that are common to all of your smart contracts: diff --git a/packages/neo-one-website/docs/1-main-concepts/09-smart-contract-apis.md b/packages/neo-one-website/docs/1-main-concepts/09-smart-contract-apis.md index a29ba417a8..c744a20f60 100644 --- a/packages/neo-one-website/docs/1-main-concepts/09-smart-contract-apis.md +++ b/packages/neo-one-website/docs/1-main-concepts/09-smart-contract-apis.md @@ -90,14 +90,14 @@ export class Contract extends SmartContract { The smart contract object returned by `createContractSmartContract` will contain one property: ```typescript -transfer(from: AddressString, to: AddressString, amount: Fixed<8>): Promise, InvocationTransaction>> +transfer(from: AddressString, to: AddressString, amount: Fixed<8>): Promise ``` Calling this method corresponds to the first step in the process. The `Promise` will resolve once the transaction has been relayed to the blockchain. The `TransactionResult` object contains two properties: ```typescript -interface TransactionResult { - readonly transaction: TTransaction; +interface TransactionResult { + readonly transaction: Transaction; readonly confirmed: (options?: GetOptions) => Promise; } ``` @@ -116,10 +116,26 @@ interface TransactionReceipt { * `Block` hash of the `Transaction` for this receipt. */ readonly blockHash: Hash256String; + /** + * `Block` time of the `Transaction` for this receipt. + */ + readonly blockTime: string; /** * Transaction index of the `Transaction` within the `Block` for this receipt. */ readonly transactionIndex: number; + /** + * Hash of the `Transaction` within the `Block` for this receipt. + */ + readonly transactionHash: Hash256String; + /** + * Ordered globally unique index of the transaction. + */ + readonly globalIndex: BigNumber; + /** + * Number of `Block`s which have confirmed this transaction. + */ + readonly confirmations: number; } ``` @@ -149,20 +165,13 @@ interface InvokeReceipt { /** - * GAS consumed by the operation. This is the total GAS consumed after the free GAS is subtracted. + * GAS consumed by the operation. */ readonly gasConsumed: BigNumber; /** - * The total GAS cost before subtracting the free GAS. - */ - readonly gasCost: BigNumber; -} - -interface InvocationResultSuccess extends InvocationResultBase { - /** - * Indicates a successful invocation + * Indicates a successful invocation. */ readonly state: 'HALT'; /** @@ -171,9 +180,13 @@ interface InvocationResultSuccess extends InvocationResultBase { readonly value: TValue; } -interface InvocationResultError extends InvocationResultBase { +interface InvocationResultError { /** - * Indicates a failed invocation + * GAS consumed by the operation. + */ + readonly gasConsumed: BigNumber; + /** + * Indicates a failed invocation. */ readonly state: 'FAULT'; /** @@ -247,30 +260,6 @@ interface SmartContract AsyncIterable; - /** - * Iterate over the logs emitted by the smart contract. - * - * @returns an `AsyncIterable` over the logs emitted by the smart contract. - */ - readonly iterLogs: (options?: SmartContractIterOptions) => AsyncIterable; - /** - * Iterate over the events and logs emitted by the smart contract. - * - * @returns an `AsyncIterable` over the events and logs emitted by the smart contract. - */ - readonly iterActions: (options?: SmartContractIterOptions) => AsyncIterable; - /** - * Converts a `RawAction`, typically from the raw results found in a `Block` to a processed `Action` or `undefined` if the action is not recognized by the ABI. - * - * @returns `Action` if the `action` parameter is recognized by the `ABI` of the smart contract, `undefined` otherwise. - */ - readonly convertAction: (action: RawAction) => Action | undefined; } ``` @@ -285,63 +274,6 @@ const tokenAddress = token.definition.networks[network].address; `client` is the `Client` that was used to create the smart contract API object, and is the underlying client used for all smart contract operations. -`iterEvents` returns an `AsyncIterable` which allows for [asynchronous iteration](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html#async-iteration) over all of the events emitted by the smart contract: - -```typescript -for await (const event of contract.iterEvents()) { - // Do something with each event -} -``` - -`iterLogs` is the same as `iterEvents` but for log notifications, i.e. unstructured strings. Note that NEO•ONE smart contracts intentionally do not support nor emit log events because any time you might want to emit a log event, we believe it's more future-proof to emit a structured event. However, when integrating with external contracts, you may want to iterate over the logs that it emits. - -`iterActions` is simply an `AsyncIterable` over both the events and logs of the smart contract in the order that they were seen. - -All of the `iter` methods accept a `SmartContractIterOptions` object: - -```typescript -/** - * Additional optional options for methods that read data from a smart contract. - */ -export interface SmartContractReadOptions { - /** - * The network to read the smart contract data for. By default this is the network of the currently selected user account. - */ - readonly network?: NetworkType; -} - -/** - * Filter that specifies (optionally) a block index to start at and (optionally) a block index to end at. - */ -export interface BlockFilter { - /** - * The inclusive start index for the first block to include. Leaving `undefined` means start from the beginning of the blockchain, i.e. index 0. - */ - readonly indexStart?: number; - /** - * The exclusive end index for the block to start at. Leaving `undefined` means continue indefinitely, waiting for new blocks to come in. - */ - readonly indexStop?: number; -} - -/** - * Additional optional options for methods that iterate over data from a smart contract. - */ -export interface SmartContractIterOptions extends SmartContractReadOptions, BlockFilter {} -``` - -The `SmartContractIterOptions` object allows specifying the `network` to iterate over and the iteration parameters, which block to start from and which block to end at. - -`convertAction` takes a `RawAction` and converts it using the ABI of the smart contract. This conversion includes parsing out the relevant events and automatically converting the raw parameters. See the [Raw Client APIs](/docs/raw-client-apis) documentation for more details. - -::: warning - -Tip - -Read more about asynchronous iteration [here](http://2ality.com/2016/10/asynchronous-iteration.html) - -::: - --- ## Type Conversion Table diff --git a/packages/neo-one-website/docs/1-main-concepts/10-testing.md b/packages/neo-one-website/docs/1-main-concepts/10-testing.md index d6401893a8..c9cfbf45cb 100644 --- a/packages/neo-one-website/docs/1-main-concepts/10-testing.md +++ b/packages/neo-one-website/docs/1-main-concepts/10-testing.md @@ -125,6 +125,12 @@ interface WithContractsOptions { * Defaults to `true`. */ readonly autoSystemFee?: boolean; + /** + * Enable logs from various systems during testing. + * + * Defaults to `false`. + */ + readonly logging?: boolean; } ``` @@ -147,6 +153,12 @@ describe('Token', () => { ## DeveloperClient +::: warning + +`DeveloperClient` has not been thoroughly tested for N3 yet and may not work at this point in time. + +::: + `DeveloperClient` is a class that is configured to point at a local development network. This class provides methods that are useful during testing: - `runConsensusNow(): Promise` - trigger consensus to run immediately. diff --git a/packages/neo-one-website/docs/1-main-concepts/11-dapps.md b/packages/neo-one-website/docs/1-main-concepts/11-dapps.md index b9c05712cf..06fadf9805 100644 --- a/packages/neo-one-website/docs/1-main-concepts/11-dapps.md +++ b/packages/neo-one-website/docs/1-main-concepts/11-dapps.md @@ -114,6 +114,12 @@ Take a look at the [@neo-one/client](/reference/@neo-one/client) reference for d ## Developer Tools +::: warning + +Developer Tools have not been thoroughly tested for N3 yet and may not work at this point in time. + +::: + NEO•ONE Developer Tools simplify the process of developing and manually testing your dapp. They contain all of the functionality necessary to control your private network: - Immediately run consensus diff --git a/packages/neo-one-website/docs/1-main-concepts/12-NEP-5.md b/packages/neo-one-website/docs/1-main-concepts/12-NEP-17.md similarity index 78% rename from packages/neo-one-website/docs/1-main-concepts/12-NEP-5.md rename to packages/neo-one-website/docs/1-main-concepts/12-NEP-17.md index 7d6f653503..91bc39d4f4 100644 --- a/packages/neo-one-website/docs/1-main-concepts/12-NEP-5.md +++ b/packages/neo-one-website/docs/1-main-concepts/12-NEP-17.md @@ -1,9 +1,9 @@ --- -slug: nep-5 -title: NEP-5 +slug: nep-17 +title: NEP-17 --- -NEP-5 is a Neo Improvement Proposal that defines a token standard for Neo smart contracts. +NEP-17 is a Neo Improvement Proposal that defines a token standard for Neo smart contracts. --- @@ -13,7 +13,7 @@ NEP-5 is a Neo Improvement Proposal that defines a token standard for Neo smart ## Properties -According to the NEP-5 standard a NEP-5 smart contract must have the following properties: +According to the NEP-17 standard a NEP-17 smart contract must have the following properties: - `decimals` - `symbol` @@ -33,7 +33,7 @@ export class Token extends SmartContract { ## Methods -According to the NEP-5 standard a NEP-5 smart contract must have the following methods: +According to the NEP-17 standard a NEP-17 smart contract must have the following methods: - `balanceOf` - `totalSupply` @@ -84,9 +84,9 @@ export class Token extends SmartContract { ## Events -According to the NEP-5 standard a NEP-5 smart contract must emit the following events: +According to the NEP-17 standard a NEP-17 smart contract must emit the following events: -- `transfer` +- `Transfer` Let's take a look at an example: @@ -94,4 +94,4 @@ Let's take a look at an example: export class Token extends SmartContract {} ``` -If all these criteria are met then the NEO•ONE compiler will produce a manifest with `"NEP-5"` included in the `supportedStandards` array. +If all these criteria are met then the NEO•ONE compiler will produce a manifest with `"NEP-17"` included in the `supportedStandards` array. diff --git a/packages/neo-one-website/docs/1-main-concepts/13-deployment.md b/packages/neo-one-website/docs/1-main-concepts/13-deployment.md index 2d8b2fec9e..d41b3310b7 100644 --- a/packages/neo-one-website/docs/1-main-concepts/13-deployment.md +++ b/packages/neo-one-website/docs/1-main-concepts/13-deployment.md @@ -13,6 +13,12 @@ Productionizing your smart contract for deployment to a network other than your --- +::: warning + +Deployment has not been thoroughly tested for N3 yet and may not work at this point in time. + +::: + ## Deployment Specifics ### Properties @@ -49,10 +55,6 @@ export class Contract extends SmartContract { } ``` -#### `payable` - -Payable determines if your contract is allowed to receive assets (like NEO and GAS). - #### `trusts` Trusts is either a wildcard string (`"*"`) or an array of strings that defines which addresses are allowed to call your contract. diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/01-forward-values.md b/packages/neo-one-website/docs/2-advanced-guides/00-forward-values.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/01-forward-values.md rename to packages/neo-one-website/docs/2-advanced-guides/00-forward-values.md diff --git a/packages/neo-one-website/docs/2-advanced-guides/00-native-assets.md b/packages/neo-one-website/docs/2-advanced-guides/00-native-assets.md deleted file mode 100644 index 43e9fb36a1..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/00-native-assets.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -slug: native-assets -title: Native Assets ---- - -Native assets like NEO and GAS require special handling in smart contracts. This guide will show you how. - -NEO employs the [Unspent Transaction Output](https://en.wikipedia.org/wiki/Unspent_transaction_output) (UTXO) system for native assets. Unfortunately, the UTXO system does not play well with smart contracts. Fortunately, NEO•ONE smart contracts abstract away most of the difficulty in handling native assets using the `@receive`, `@send`, `@sendUnsafe` and `@claim` [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html). - -One commonality between every native asset method is that they must throw an error if the transaction should not proceed. - ---- - -[[toc]] - ---- - -## Receive Native Assets - -Decorate a method with `@receive` to allow the method to be invoked when receiving native assets: - -```typescript -export class Contract extends SmartContract { - @receive - public mintTokens(): void { - // Use Blockchain.currentTransaction to validate and process the inputs/outputs. - // Throw an error if it's an invalid combination - } -} -``` - -Methods decorated with `@receive` may also be decorated with `@sendUnsafe` to enable both sending and receiving assets to be verified by the method. - -Invoking a method marked with `@receive` is identical to a normal method, but the transaction options contain an additional property, `sendTo`, which can be used to specify the assets to send to the smart contract: - -```typescript -const receipt = await contract.mintTokens({ - sendTo: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - }, - ], -}); -``` - -There are cases where a smart contract may receive native assets without a corresponding `@receive` method invocation, or sometimes even when the `@receive` method throws an error. Unfortunately this is unavoidable, and to solve these cases every smart contract has an automatically generated method called `refundAssets`. Users may call this method when they have sent assets to the contract that were not properly processed. Using the NEO•ONE client APIs: - -```typescript -const transactionHash = ... // Hash of the transaction that needs to be refunded -const receipt = await contract.refundAssets.confirmed(transactionHash); -``` - ---- - -## Send Native Assets - -NEO•ONE provides two methods for sending assets, one that is "unsafe" and one that is "safe". - -### Unsafe - -Decorate a method with `@sendUnsafe` to enable assets to be sent from the contract in a single transaction: - -```typescript -export class Contract extends SmartContract { - @sendUnsafe - public withdraw(): void { - // Typically check something like Address.isCaller(this.owner) - } -} -``` - -`@sendUnsafe` is unsafe because it potentially allows the equivalent of double spends. It's possible for a user to construct a series of parallel transactions that enable them to withdraw more than they should be allowed to. - -::: warning - -Note - -Only decorate a method with `@sendUnsafe` when the method checks that the caller is a "superuser", i.e. someone who is not going to attempt to cheat the contract. The most common case is to simply call `Address.isCaller(this.owner)` which checks that the method was only invoked by the owner of the smart contract. - -::: - -Calling a method marked with `@sendUnsafe` is similar to `@receive` in that it allows an additional options property called `sendFrom` which lets the user specify assets to transfer from the contract: - -```typescript -const receipt = await contract.withdraw.confirmed({ - sendFrom: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - to: 'APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR', - }, - ], -}); -``` - -### Safe - -Decorate a method with `@send` to enable assets to be sent from the contract safely. `@send` requires two transactions to send assets from the contract. At a high level the steps are: - -1. The user "marks" the assets they wish to withdraw from the contract by constructing a transaction that sends those assets back to the smart contract. -2. The user constructs a transaction that withdraws the previously "mark"ed assets to the desired address. - -NEO•ONE abstract this process such that you only need to define a method decorated with `@send` that throws an error on invalid transactions. NEO•ONE handles the rest. This method may also accept a final argument, a `Transfer` object, that contains the details of the pending transfer: - -```typescript -interface Transfer { - readonly amount: Fixed<8>; - readonly asset: Hash256; - readonly to: Address; -} -``` - -For example, if you wanted to have a method that required a single argument, `value`, of type `string`, you could define your method like so: - -```typescript -export class Contract extends SmartContract { - @send - public withdraw(value: string, transfer: Transfer): void { - // Validate the `transfer` should proceed. Throw an error if not. - } -} -``` - -Calling a method marked with `@send` is identical to `@sendUnsafe`, however, the transfer will not occur until the `completeSend` method is invoked with the transaction hash of the first transaction: - -```typescript -// This transaction only sends assets from the contract to itself, -// marking them for withdrawal by a followup transaction. -const receipt = await contract.withdraw.confirmed('value', { - sendFrom: [ - { - asset: Hash256.NEO, - amount: new BigNumber(10), - to: 'APyEx5f4Zm4oCHwFWiSTaph1fPBxZacYVR', - }, - ], -}); -// Complete the withdrawal process using the transaction hash -const finalReceipt = await contract.completeSend.confirmed(receipt.transaction.hash); -``` - ---- - -## Claim GAS - -Decorate a method with `@claim` to enable claiming GAS. `@claim` methods have a few restrictions: - -1. `@claim` methods may not modify contract storage. They act like `@constant` methods. -2. `@claim` methods may not access `Blockchain.currentTransaction`, instead they may optionally accept the `ClaimTransaction` that the method was invoked in as the final argument. - -```typescript -export class Contract extends SmartContract { - @claim - public claim(transaction: ClaimTransaction): void { - // Validate the ClaimTransaction and throw an error if it is invalid - } -} -``` - -The NEO•ONE client APIs currently only support claiming all available GAS for a smart contract and sending that GAS back to the smart contract. If you have another use-case that you'd like to see supported, please reach out on [Discord](https://discordapp.com/invite/S86PqDE) or open an issue on [GitHub](https://github.com/neo-one-suite/neo-one/issues/new). - -```typescript -await contract.claim.confirmed(); -``` - -::: warning - -Note - -`@claim` is similar to `@sendUnsafe` in terms of safety and thus you should only allow GAS claims that transfer the GAS to an `Address` that is not the contract itself to be done by superusers. To enable GAS claims for contracts without owners or superusers, instead only allow GAS claims that send the GAS back to the contract, and then implement transferring the GAS to the rightful owner using a method marked with `@send`. - -::: diff --git a/packages/neo-one-website/docs/2-advanced-guides/01-forward-values.md b/packages/neo-one-website/docs/2-advanced-guides/01-forward-values.md deleted file mode 100644 index c48289c899..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/01-forward-values.md +++ /dev/null @@ -1,99 +0,0 @@ ---- -slug: forward-values -title: Forward Values ---- - -Forward values allow advanced interactivity between smart contracts, enabling use-cases that would not normally be possible. - ---- - -[[toc]] - ---- - -## Forward Value - -Before we dive into the specifics, let's look at an example of how forward values are used: - -```typescript -interface TokenPayableContract { - readonly approveReceiveTransfer: (from: Address, value: Fixed<8>, ...args: ForwardValue[]) => boolean; -} - -export class Token extends SmartContract { - // Note that the implementation here is only to show how we - // can use forward values and is an incomplete implementation of a - // Token transfer method. - public transfer(from: Address, to: Address, value: Fixed<8>, ...args: ForwardValue[]): boolean { - const contract = Contract.for(to); - if (contract !== undefined) { - const payableContract = SmartContract.for(to); - - return payableContract.approveReceiveTransfer(from, value, ...args); - } - - return true; - } -} -``` - -::: warning - -Note - -We're using a [rest](https://www.typescriptlang.org/docs/handbook/functions.html#rest-parameters) parameter as the final parameter of the `transfer` method. Declaring a rest parameter means that the function will accept 0 or more additional arguments of that type. - -::: - -`ForwardValue`s represent any type. They're opaque to the contract that declared them. Instead of using them directly, the contract forwards them to another contract. In the example above we check to see if the target or `to` `Address` is a smart contract. If it is, we get an instance of it and invoke the `approveReceiveTransfer` method, forwarding any additional arguments that we received in the call to `transfer`. - -This pattern allows the target contract a chance to react to the transfer, as well as allows the user to provide any additional arguments the contract may require to react to the transfer. - ---- - -## Forwarded Value - -The counterpart to `ForwardValue` is the tagged type `ForwardedValue`. `ForwardedValue` tags the type `T` such that the NEO•ONE toolchain will generate client APIs that simplify forwarding values. Given the following smart contract: - -```typescript -export class Escrow extends SmartContract { - public approveReceiveTransfer(from: Address, value: Fixed<8>, to: ForwardedValue
): boolean { - // Update the escrow account for [from, to] with value - return true; - } -} -``` - -The NEO•ONE toolchain will generate a method called `forwardApproveReceiveTransferArgs`: - -```typescript -const receipt = await token.transfer.confirmed( - from, - escrow.definition.networks[networkName].address, - value, - ...escrow.forwardApproveReceiveTransferArgs(to), -); -``` - -The `forwardApproveReceiveTransferArgs` call above not only sets up the call to forward the specified arguments, but it additionally adds the `Escrow` contracts events (if any) to the resulting `receipt`. - -Forwarding values also works recursively. For example, if the `Escrow` contract also specified a rest parameter of `ForwardValue`s and called another smart contract `Foo`'s `bar` method that expected a `ForwardedValue`, the client API invocation would look like: - -```typescript -const receipt = await token.transfer.confirmed( - from, - escrow.definition.networks[networkName].address, - value, - ...escrow.forwardApproveReceiveTransferArgs(to, ...foo.forwardBarArgs('value')), -); -``` - -In this case, the `receipt` would contain the events for the `transfer` call, the `approveReceiveTransfer` call and the `bar` call. - ---- - -## Reactive Smart Contracts - -Reactive smart contracts are powerful and enable many use-cases that would otherwise not be possible. We recommend the following pattern when implementing your smart contracts. - -Whenever your smart contract has a method that takes an `action` on an `Address`, always check to see if the target `Address` is a smart contract. If it is, invoke the `approveReceive` method of that smart contract with the same arguments `action` was called with, except the argument that is the smart contract `Address` itself. Additionally, pass a rest parameter of `ForwardValue`s to the method. Take a look at the `Token` example above to see this pattern in action. diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/02-user-accounts.md b/packages/neo-one-website/docs/2-advanced-guides/01-user-accounts.md similarity index 98% rename from packages/neo-one-website/docs-old/2-advanced-guides/02-user-accounts.md rename to packages/neo-one-website/docs/2-advanced-guides/01-user-accounts.md index 009c20ff76..d9de485670 100644 --- a/packages/neo-one-website/docs-old/2-advanced-guides/02-user-accounts.md +++ b/packages/neo-one-website/docs/2-advanced-guides/01-user-accounts.md @@ -109,6 +109,10 @@ interface UserAccount { * The public key for the address. */ readonly publicKey: PublicKeyString; + /** + * The signature redemption contract of the account. + */ + readonly contract: AccountContract; } ``` diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/03-extended-client-apis.md b/packages/neo-one-website/docs/2-advanced-guides/02-extended-client-apis.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/03-extended-client-apis.md rename to packages/neo-one-website/docs/2-advanced-guides/02-extended-client-apis.md diff --git a/packages/neo-one-website/docs/2-advanced-guides/02-user-accounts.md b/packages/neo-one-website/docs/2-advanced-guides/02-user-accounts.md deleted file mode 100644 index 009c20ff76..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/02-user-accounts.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -slug: user-accounts -title: User Accounts ---- - -NEO•ONE client APIs revolve around the concept of user accounts which represent a single address controlled by the user of the dapp. - -The `Client` class is an abstraction layer over `UserAccountProvider`s which implement the core logic. By using the `Client` class and the generated smart contract APIs throughout your dapp, you can ensure that your business logic is independent of the underlying `UserAccountProvider`s. - ---- - -[[toc]] - ---- - -## Client Configuration - -The `createClient` helper function generated by the NEO•ONE toolchain is configured with a `LocalUserAccountProvider` backed by an in-memory `LocalKeyStore` by default. This can be easily configured by passing in a callback of the form: - -```typescript -(provider: NEOONEProvider) => { [name: string]: UserAccountProvider } -``` - -This callback will be passed a default `NEOONEProvider` that's been configured to work with your local private network as well as public nodes for the TestNet and MainNet. The return value will be used to configure the `Client`. - -::: warning - -Tip - -You can configure the `Client` to only work with external wallets provided by an extension or a dapp browser by checking `process.env.NODE_ENV === 'production'` and returning a subset of the `UserAccountProvider`s used during development. - -::: - -Let's take a look at an example: - -```typescript -const getUserAccountProviders = (provider: NEOONEProvider) => { - const dapp = new DappBrowserUserAccountProvider(); - const extension = new BrowserExtensionUserAccountProvider(); - const other = new SomeOtherWalletProvider(); - if (process.env.NODE_ENV === 'production') { - return { dapp, extension, other }; - } - - const memory = new LocalUserAccountProvider({ - keystore: new LocalKeyStore(new LocalMemoryStore()), - provider, - }); - - return { dapp, extension, other, memory }; -}; - -const client = createClient(getUserAccountProviders); -``` - -This would configure a `Client` that knows how to communicate with a dapp browser (e.g. nOS), a browser extension (e.g. NEX) and some other integration provided by `SomeOtherWalletProvider`. In production, it would only communicate with those providers, while in development we've additionally configured a `LocalUserAccountProvider` with an in-memory `LocalKeyStore` for use in testing. - -::: warning - -Note - -In order to take advantage of the automatic local network configuration and pre-configured wallets, you must configure a `LocalUserAccountProvider` using the argument `provider` and an in-memory keystore, like the above example. - -::: - ---- - -## LocalUserAccountProvider - -`LocalUserAccountProvider` is a completely local to the application `UserAccountProvider` which directly connects to NEO•ONE RPC nodes in order to process read requests as well as create and send transactions. `LocalUserAccountProvider` must be configured with a `KeyStore` instance and a `Provider` instance. The `KeyStore` interface abstracts over `UserAccount`s, selecting them, getting the current one, as well as signing a message with a specified `UserAccount`. The `Provider` interface abstracts over specific RPC requests the `LocalUserAccountProvider` requires to function. - -In the example above, we've configured it to use a `LocalKeyStore` which is backed by a `LocalMemoryStore` which provides `UserAccount`s via an in-memory store. `LocalKeyStore` can be configured with any object that implements the `Store` interface and can be easily backed by persistent storage in files or within browser local storage: - -```typescript -import localforage from 'localforage'; - -const localStorage = new LocalUserAccountProvider({ - keystore: new LocalKeyStore(new LocalStringStore(localforage)), - provider, -}); -``` - -NEO•ONE currently also supports a `LedgerKeyStore`, which enables connecting to ledger devices in both NodeJS-like environments and browser-like environments. - -```typescript -const ledger = new LocalUserAccountProvider({ - keystore: new LedgerKeyStore(provider), - provider, -}); -``` - ---- - -## UserAccount and UserAccountID - -`UserAccount` is the main abstraction used to define the user's available accounts for signing transactions. It contains three properties: - -```typescript -interface UserAccount { - /** - * Uniquely identifies a `UserAccount` by its address and the network its used on. - */ - readonly id: UserAccountID; - /** - * The name to use when displaying this account in a user-facing UI. Can be a user configured name or just the address. - */ - readonly name: string; - /** - * The public key for the address. - */ - readonly publicKey: PublicKeyString; -} -``` - -`UserAccountID` is used throughout the `@neo-one/client` APIs to specify a particular account to take an action with. For example, all of the smart contract APIs accept an options object as the last parameter that can specify a `from` `UserAccountID` to invoke a method with. - ---- - -## Integrating With NEO•ONE - -Want to integrate your wallet with NEO•ONE? Then this section is for you. The best way to integrate is to use the NEO•ONE client APIs with a `LocalUserAccountProvider` within your wallet. As described above, the `LocalUserAccountProvider` can be customized with specific `KeyStore` implementations that should satisfy the majority of wallet use-cases. - -Once you've done that, come talk to us on [Discord](https://discord.gg/S86PqDE). The integration is currently a work in progress, but it's coming very soon. diff --git a/packages/neo-one-website/docs/2-advanced-guides/03-extended-client-apis.md b/packages/neo-one-website/docs/2-advanced-guides/03-extended-client-apis.md deleted file mode 100644 index 713d9a4b86..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/03-extended-client-apis.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -slug: extended-client-apis -title: Extended Client APIs ---- - -The extended client APIs are targeted at users that require more information from the blockchain than a typical dapp. - -The primary use-case for the extended client APIs are for implementing block explorers and applications with similar requirements. Documentation coming soon! diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/04-raw-client-apis.md b/packages/neo-one-website/docs/2-advanced-guides/03-raw-client-apis.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/04-raw-client-apis.md rename to packages/neo-one-website/docs/2-advanced-guides/03-raw-client-apis.md diff --git a/packages/neo-one-website/docs/2-advanced-guides/04-raw-client-apis.md b/packages/neo-one-website/docs/2-advanced-guides/04-raw-client-apis.md deleted file mode 100644 index 66feb9223a..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/04-raw-client-apis.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -slug: Raw-client-apis -title: Raw Client APIs ---- - -Similar to the [Extended Client APIs](/docs/extended-client-apis), the raw client APIs are targeted at users that require more information from the blockchain than a typical dapp. - -Documentation coming soon! diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/05-react.md b/packages/neo-one-website/docs/2-advanced-guides/04-react.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/05-react.md rename to packages/neo-one-website/docs/2-advanced-guides/04-react.md diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/06-angular.md b/packages/neo-one-website/docs/2-advanced-guides/05-angular.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/06-angular.md rename to packages/neo-one-website/docs/2-advanced-guides/05-angular.md diff --git a/packages/neo-one-website/docs/2-advanced-guides/05-react.md b/packages/neo-one-website/docs/2-advanced-guides/05-react.md deleted file mode 100644 index d9b7ad9404..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/05-react.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -slug: react -title: React ---- - -NEO•ONE has first-class integration with React applications. - -Integrating NEO•ONE with React is a breeze using the generated NEO•ONE client APIs. We also offer a `FromStream` component that make using `Observable`s in the client APIs within your React components much simpler. - ---- - -[[toc]] - ---- - -## Generated Code - -The NEO•ONE toolchain emits two components that aid in integrating a React application with NEO•ONE: `ContractsProvider` and `WithContracts`. - -### ContractProvider - -The `ContractsProvider` component should be used at the root of your application as it provides the NEO•ONE client and smart contract APIs to all children in its React tree using the [React context API](https://reactjs.org/docs/context.html): - -```tsx -import { ContractsProvider } from './neo-one'; -import * as ReactDOM from 'react-dom'; -import { App } from './App'; - -const app = ( - - - -); -ReactDOM.render(app, document.getElementById('app')); -``` - -`ContractsProvider` by default uses the generated helper methods to create the required props, but you may customize this by passing in your own `Client`, `DeveloperClient`s and/or `LocalClient`s: - -```tsx -import { ContractsProvider, createClient } from './neo-one'; -import * as ReactDOM from 'react-dom'; -import { App } from './App'; - -const client = createClient(); -const app = ( - - - -); -ReactDOM.render(app, document.getElementById('app')); -``` - -### WithContracts - -Once you've included `ContractsProvider` in your application, you may use the `WithContracts` component anywhere in your application to access the NEO•ONE client APIs. `WithContracts` is is a [render props](https://reactjs.org/docs/render-props.html) component that passes the `client` and your smart contract APIs to its child function: - -```tsx -{({ token }) =>
token.withdraw.confirmed()}>Withdraw
}
-``` - ---- - -## FromStream - -`@neo-one/react` contains one export, the `FromStream` component. `FromStream` is a [render props](https://reactjs.org/docs/render-props.html) component that subscribes to the `Observable` returned from invoking the `createStream` prop. It then passes the most recently emitted value to its children function: - -```tsx - - {({ client }) => ( - client.block$}> - {(block) =>
The current block index is: {block.index}
} -
- )} -
-``` - -`FromStream` accepts one additional prop, `props`, which is a list of values that are used within the `createStream` function. Without `props`, `createStream` is called on every render of `FromStream` and the result is subscribed to. With `props`, a new stream is subscribed to only when the value of one of the elements of `props` does not match the previous render. In general, you should go ahead and include any values you use in your `createStream` function within the `props` prop. diff --git a/packages/neo-one-website/docs/2-advanced-guides/06-angular.md b/packages/neo-one-website/docs/2-advanced-guides/06-angular.md deleted file mode 100644 index ea311167b5..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/06-angular.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -slug: angular -title: Angular ---- - -NEO•ONE has first-class integration with Angular applications. - -Integrating NEO•ONE with Angular is a breeze using the generated NEO•ONE client APIs. - ---- - -[[toc]] - ---- - -## Generated Code - -The NEO•ONE toolchain emits an [Angular Service](https://angular.io/guide/dependency-injection#injecting-services) that aids in integrating an Angular application with NEO•ONE: `ContractsService`. - -### ContractsService - -The `ContractsService` can be injected into any component or service in which you need access to the client APIs or smart contract methods. - -```typescript -import { Component } from '@angular/core'; -import { ContractsService } from './neo-one'; - -@Component({ - selector: 'app-test-component', - templateUrl: './test-component.component.html', - styleUrls: ['./test-component.component.css'], -}) -export class TestComponent implements OnInit { - constructor(private contractsService: ContractsService) {} - - onWithdraw(): void { - this.contractsService.token.withdraw - .confirmed() - .then - // update something - (); - } -} -``` - -The `ContractsService` makes responding to updates in the blockchain easy by providing access to [Observables](https://angular.io/guide/observables-in-angular). Here's how you might use the `ContractsService` to build a simple Angular component to update the current block count. - -```typescript -import { Component, OnInit } from '@angular/core'; -import { ContractsService } from './neo-one'; - -@Component({ - selector: 'block-counter-component', - templateUrl: './block-counter.component.html', - styleUrls: ['./block-counter.component.css'], -}) -export class BlockCounter implements OnInit { - blockCount: number; - - constructor(private contractsService: ContractsService) { - this.blockCount = 0; - } - - ngOnInit() { - this.getBlocks(); - } - - getBlocks(): void { - this.contractsService.client.block$.subscribe((block) => { - this.blockCount = block.block.index; - }); - } -} -``` - -### Important Notes - -- For the smoothest experience using NEO•ONE with Angular 6+, you should use the browserified version of NEO•ONE. This version of NEO•ONE replaces Node.js builtin modules with their browser compatible shims. To use this version, you simply need to import any NEO•ONE client modules with the `-browserify` suffix. So, `@neo-one/client` is imported as `@neo-one/client-browserify`. -- `allowSyntheticDefaultImports` must be set to `true` in the top level `tsconfig.json`. -- `(window as any).global = window;` must be added in the `polyfill.ts` file. diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/07-vue.md b/packages/neo-one-website/docs/2-advanced-guides/06-vue.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/07-vue.md rename to packages/neo-one-website/docs/2-advanced-guides/06-vue.md diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/08-dapi-support.md b/packages/neo-one-website/docs/2-advanced-guides/07-dapi-support.md similarity index 100% rename from packages/neo-one-website/docs-old/2-advanced-guides/08-dapi-support.md rename to packages/neo-one-website/docs/2-advanced-guides/07-dapi-support.md diff --git a/packages/neo-one-website/docs/2-advanced-guides/07-vue.md b/packages/neo-one-website/docs/2-advanced-guides/07-vue.md deleted file mode 100644 index 1897847ed3..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/07-vue.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -slug: vue -title: Vue ---- - -NEO•ONE has integration with Vue applications. - -Integrating NEO•ONE with Vue is a breeze using the generated NEO•ONE client APIs. - ---- - -[[toc]] - ---- - -## Generated Code - -The NEO•ONE toolchain emits a service that aids in integrating a Vue application with NEO•ONE: `contractsService`. - -### ContractsService - -The `contractsService` is a singleton which provides access to all of the generated NEO•ONE client APIs and smart contract methods. - -```typescript - - - -``` - -The `contractsService` makes responding to updates in the blockchain easy by providing access to observables. Here's how you might use the `contractsService` to build a simple Vue component to update the current block count. - -```typescript - - - -``` diff --git a/packages/neo-one-website/docs-old/2-advanced-guides/09-configuration-options.md b/packages/neo-one-website/docs/2-advanced-guides/08-configuration-options.md similarity index 98% rename from packages/neo-one-website/docs-old/2-advanced-guides/09-configuration-options.md rename to packages/neo-one-website/docs/2-advanced-guides/08-configuration-options.md index 8089421fb1..accfabd4d9 100644 --- a/packages/neo-one-website/docs-old/2-advanced-guides/09-configuration-options.md +++ b/packages/neo-one-website/docs/2-advanced-guides/08-configuration-options.md @@ -25,13 +25,13 @@ export default { // NEO•ONE will look for smart contracts in this directory. path: 'neo-one/contracts', // Set this to true if you want the compile command to output JSON. - // json: true, + json: true, // Set this to true if you want the compile command to output AVM. - // avm: false, + avm: false, // Set this to true if you want the compile command to output additional debug information. - // debug: false, + debug: false, // Set this to true if you want the compile command to output the AVM in a human-readable format for debugging (requires debug: true). - // opcodes: false, + opcodes: false, }, artifacts: { // NEO•ONE will store build and deployment artifacts that should be checked in to vcs in this directory. diff --git a/packages/neo-one-website/docs/2-advanced-guides/08-dapi-support.md b/packages/neo-one-website/docs/2-advanced-guides/08-dapi-support.md deleted file mode 100644 index 05bee9d5c2..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/08-dapi-support.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -slug: dapi-support -title: dAPI Support ---- - -NEO•ONE provides dAPI support through the familiar [User Accounts](/docs/user-accounts) interface. - ---- - -[[toc]] - ---- - -## What is the dAPI? - -The dAPI is an interface for interacting with the NEO blockchain using an existing dAPI enabled wallet provider. This means that actions like transferring NEO, claiming GAS, and invoking smart contracts can be handled by a trusted wallet provider without the user every having to give a new dApp access to their private key. This allows developers to focus on the development of their dApp without having to worry about the complexities and security concerns of managing user accounts. - -## DapiUserAccountProvider - -NEO•ONE abstracts away the dAPI into a `DapiUserAccountProvider`, an implementation of the [UserAccountProvider](/reference/@neo-one/client/useraccountprovider) interface. While the [LocalUserAccountProvider](/reference/@neo-one/client/localuseraccountprovider) provides a [Client](/reference/@neo-one/client/client) access to [User Accounts](/docs/user-accounts) stored locally, the `DapiUserAccountProvider` provides access to [User Accounts](/docs/user-accounts) stored by a wallet provider and accessed through the dAPI. - -To set up a `DapiUserAccountProvider`, simply import `neo-dapi` in your entry point and ensure it has been attached to the global object. We recommend using the [globalThis](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis) as it is compatible across environments. Once the `neo-dapi` has been attached to the global object, it can be passed from the global object into the constructor of a new `DapiUserAccountProvider`. With this setup, a dAPI enabled wallet running in the background will automatically be used to handle any `UserAccountProvider` methods. The `DapiUserAccountProvider` can then be used in place of a `LocalUserAccountProvider` when setting up a NEO•ONE `Client` as detailed in the [User Accounts](/docs/user-accounts) section. - -Entry point: - -```typescript -import neoDapi from 'neo-dapi'; - -// Attach the neo-dapi to the global object at the entry point -globalThis.neoDapi = neoDapi; -``` - -Elsewhere: - -```typescript -import { Client, DapiUserAccountProvider } from '@neo-one/client'; - -... - -const dapiUserAccountProvider = new DapiUserAccountProvider({ - // Use the global object to pass the neo-dapi to a DapiUserAccountProvider - dapi: globalThis.neoDapi, - provider, - onError: (error) => { - throw error; - }, -}); - -// Use the DapiUserAccountProvider to create a Client -const client = new Client({ dapi: dapiUserAccountProvider }); -``` - -## Codegen - -If you're using NEO•ONE to compile smart contracts and/or generate code with the `neo-one build` command, setting up the dAPI is even easier. Just make sure to attach the `neo-dapi` to the global object at your project's entry point and have a dAPI enabled wallet running in the background. The rest will be taken care of for you when you run `neo-one build`. The generated `Client` will automatically detect the `neo-dapi` attached to the global object and provide it access to a `DapiUserAccountProvider`. Note: This feature is only available with node version >= 12. - -## RemoteUserAccountProvider - -If for some reason the dAPI does not suit the needs for your dApp, NEO•ONE also provides a general `RemoteUserAccountProvider`. This allows communication between a `RemoteUserAccountProvider` in a dApp and a [UserAccountProvider](/reference/@neo-one/client/useraccountprovider) in a wallet through a [Message Channel](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel) interface. To use as `RemoteUserAccountProvider`, a wallet provider must implement a [UserAccountProvider](/reference/@neo-one/client/useraccountprovider), such as a [LocalUserAccountProvider](/reference/@neo-one/client/localuseraccountprovider) and call `connectRemoteUserAccountProvider` with the [UserAccountProvider](/reference/@neo-one/client/useraccountprovider) and the [Message Port](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) to define the channel. On the dApp's side, all that is required is to create a new `RemoteUserAccountProvider` with the other [Message Port](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort). Note this feature should only be used in cases where the dAPI is insufficient, as the dAPI is the official standard for the NEO blockchain. If you'd like to use a `RemoteUserAccountProvider`, please contact us so we can work with you to ensure it meets the needs of your dApp. diff --git a/packages/neo-one-website/docs/2-advanced-guides/09-configuration-options.md b/packages/neo-one-website/docs/2-advanced-guides/09-configuration-options.md deleted file mode 100644 index 8089421fb1..0000000000 --- a/packages/neo-one-website/docs/2-advanced-guides/09-configuration-options.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -slug: config-options -title: Configuration Options ---- - -NEO•ONE compiler configuration options. - -Configure NEO•ONE for your project. - -## Config File - -An [initialized environment](https://neo-one.io/tutorial#Setup-for-the-Tutorial) will have a `.neo-one.config.ts` file within the project root. - -### Example NEO•ONE configuration file - -The `.neo-one.config.ts` configuration file may look something like this: - -```typescript -import { defaultNetworks } from '@neo-one/cli'; - -export default { - contracts: { - // The NEO•ONE compile command will output the compile results in this directory. - outDir: 'neo-one/compiled', - // NEO•ONE will look for smart contracts in this directory. - path: 'neo-one/contracts', - // Set this to true if you want the compile command to output JSON. - // json: true, - // Set this to true if you want the compile command to output AVM. - // avm: false, - // Set this to true if you want the compile command to output additional debug information. - // debug: false, - // Set this to true if you want the compile command to output the AVM in a human-readable format for debugging (requires debug: true). - // opcodes: false, - }, - artifacts: { - // NEO•ONE will store build and deployment artifacts that should be checked in to vcs in this directory. - path: 'neo-one/artifacts', - }, - migration: { - // NEO•ONE will load the deployment migration from this path. - path: 'neo-one/migration.ts', - }, - codegen: { - // NEO•ONE will write source artifacts to this directory. This directory should be committed. - path: 'src/neo-one', - // NEO•ONE will generate code in the language specified here. Can be one of 'javascript' or 'typescript'. - language: 'typescript', - // NEO•ONE will generate client helpers for the framework specified here. Can be one of 'react', 'angular', 'vue' or 'none'. - framework: 'react', - // Set this to true if you're using an environment like Expo that doesn't handle browserifying dependencies automatically. - browserify: false, - // Set this to true if you're running in codesandbox to workaround certain limitations of codesandbox. - codesandbox: false, - }, - network: { - // NEO•ONE will store network data here. This path should be ignored by your vcs, e.g. by specifiying it in a .gitignore file. - path: '.neo-one/network', - // NEO•ONE will start the network on this port. - port: 9040, - }, - // NEO•ONE will configure various parts of the CLI that require network accounts using the value provided here, for example, when deploying contracts. - // Refer to the documentation at https://neo-one.io/docs/config-options for more information. - networks: defaultNetworks, - neotracker: { - // NEO•ONE will start an instance of NEO Tracker using this path for local data. This directory should not be committed. - path: '.neo-one/neotracker', - // NEO•ONE will start an instance of NEO Tracker using this port. - port: 9041, - // Set to false if you'd like NEO•ONE to start an instance of NEO Tracker when running 'neo-one build'. You will need @neotracker/core installed as a dependency for this to work. - skip: true, - }, -}; -``` - -## Networks - -While we provide defaults for deployment networks it is also possible to use your own! You can provide a `name` and `rpcUrl` to our helper function `createUserAccountProviderFunc` from `@neo-one/cli`, which will prompt you to provide a list of `privateKeys` for use on the network when deploying: - -```typescript -import { createUserAccountProviderFunc, defaultNetworks } from '@neo-one/cli'; - -export default { - // ... - networks: { - ...defaultNetworks, - exampleNetwork: createUserAccountProviderFunc('exampleNetwork', 'exampleRpcUrl.io/rpc'); - } - // ... -} -``` - -This is what the `createUserAccountProviderFunc` will do to create the new `LocalUserAccountProvider`: - -```typescript -export const createUserAccountProviderFunc = (network: string, rpcURL: string) => async () => { - const keystore = new LocalKeyStore(new LocalMemoryStore()); - const { privateKeys } = await prompts({ - type: 'list', - name: 'privateKeys', - message: `Please enter one or more private keys separated by commas for use on the "${network}" network.`, - validate: (value) => (value.length > 0 ? true : 'Must enter at least one private key.'), - }); - await Promise.all(privateKeys.map((privateKey: string) => keystore.addUserAccount({ network, privateKey }))); - - return new LocalUserAccountProvider({ - keystore, - provider: new NEOONEProvider([{ network, rpcURL }]), - }); -}; -``` - -Or you can create your own hard-coded `async` function that returns a `UserAccountProvider`, like so: - -```typescript -export default { - // ... - networks: { - ...defaultNetworks, - exampleNetwork: async () => { - const keystore = new LocalKeyStore(new LocalMemoryStore()); - await keystore.addUserAccount('exampleNetwork', 'PRIVATE_KEY'); - - return new LocalUserAccountProvider({ - keystore, - provider: new NEOONEProvider([{ network: 'exampleNetwork', rpcUrl: 'exampleRpcUrl.io/rpc' }]), - }); - }, - }, - // ... -}; -``` - -::: warning - -Note - -While hard-coding the `LocalUserAccountProvider` is a viable option in testing this also requires storing a private key as plain text in the `.neo-one.config.ts` file that is traditionally checked into version control, like Git/GitHub. For this reason we recommend only using a hard coded private key value for local on-the-fly testing and debugging. - -::: diff --git a/packages/neo-one-website/docs/3-node/4-build-from-source.md b/packages/neo-one-website/docs/3-node/4-build-from-source.md index c5d1fb2c38..ec988740e1 100644 --- a/packages/neo-one-website/docs/3-node/4-build-from-source.md +++ b/packages/neo-one-website/docs/3-node/4-build-from-source.md @@ -20,6 +20,7 @@ This can be useful for local debugging and if you would like to make your own co - Windows: We recommend using [Chocolatey](https://chocolatey.org/). - [Yarn](https://yarnpkg.com/) (recommended) - [RushJS](https://rushjs.io/) +- [C# .NET](https://docs.microsoft.com/en-us/dotnet/) version 3.1.401 --- @@ -71,3 +72,15 @@ node neo-one-node --config /path/to/config.json --environment.logger.level=trace ``` You can also add a `.neo-onerc` configuration file anywhere in the app directory (recommended at the root of the repo directory) to apply your configuration by default. See [rc](https://github.com/dominictarr/rc#rc) for more informatio on how NEO•ONE will find and apply the node configuration with an `rc` file. + +## Troubleshooting + +You may or may not run into environment problems when trying to run the node. The NEO•ONE node now uses the C# NeoVM instead of our own implementation of the NeoVM in TypeScript, which means that NEO•ONE controls C# code through some complicated mechanisms. If you run into problems with running the node then try these steps: + +- Add these environment variables to your shell environment: + - `EDGE_USE_CORECLR=1` + - `EDGE_APP_ROOT=/node_modules/@neo-one/node-vm/lib/Debug/netcoreapp3.0` +- Install `pkgconfig` on macOS with Homebrew: `brew install pkgconfig` + - Then add this environment variable: `PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig` + - You then need to re-install your node modules by deleting the `node_modules` folder and then running `npm install` again +- If problems persist then please reach out to us on [Discord](https://discord.gg/S86PqDE) diff --git a/packages/neo-one-website/src/components/home/Home.tsx b/packages/neo-one-website/src/components/home/Home.tsx index b9d9173576..815bb512c6 100644 --- a/packages/neo-one-website/src/components/home/Home.tsx +++ b/packages/neo-one-website/src/components/home/Home.tsx @@ -156,7 +156,7 @@ export const Home = (props: {}) => ( - + {/* */} ); diff --git a/packages/neo-one-website/tutorial/tutorial.md b/packages/neo-one-website/tutorial/tutorial.md index 5a7257180c..5d9a583b8d 100644 --- a/packages/neo-one-website/tutorial/tutorial.md +++ b/packages/neo-one-website/tutorial/tutorial.md @@ -55,42 +55,58 @@ Here's how to setup your local development environment: - Linux and Mac: We recommend using [Node Version Manager](https://github.com/creationix/nvm). - Windows: We recommend using [Chocolatey](https://chocolatey.org/). -2. Follow the [installation instructions for Create React App](https://reactjs.org/docs/create-a-new-react-app.html#create-react-app) to make a new project. +2. Install [C# .NET](https://docs.microsoft.com/en-us/dotnet/) version 3.1.401 -- Be sure to invoke Create React App with the `--typescript` flag in order to enable TypeScript support: `npx create-react-app token --typescript` +3. Add a `global.json` file to the root of your project repo with this JSON: -3. Change your current working directory into your new `token` directory created by `create-react-app` by running `cd token` or `cd ` +```json +{ + "sdk": { + "version": "3.1.401" + } +} +``` -4. Install NEO•ONE using either [yarn](https://yarnpkg.com/) +This tells your local C# .NET runtime to use version 3.1.401 in this repo, even if you have newer versions installed on your machine. -```bash -yarn add @neo-one/suite -``` +4. Follow the [installation instructions for Create React App](https://reactjs.org/docs/create-a-new-react-app.html#create-react-app) to make a new project. -or [npm](https://www.npmjs.com/) +- Be sure to invoke Create React App with the `--typescript` flag in order to enable TypeScript support: `npx create-react-app token --typescript` -```bash -npm install @neo-one/suite -``` +5. Change your current working directory into your new `token` directory created by `create-react-app` by running `cd token` or `cd ` -alternatively, install the individual packages `@neo-one/suite` wraps for you: +6. Install NEO•ONE using either [yarn](https://yarnpkg.com/) ```bash -yarn add @neo-one/cli @neo-one/client @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +yarn add @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` ```bash -npm install @neo-one/cli @neo-one/client @neo-one/smart-contract @neo-one/smart-contract-test @neo-one/smart-contract-lib @neo-one/smart-contract-typescript-plugin +npm install @neo-one/cli@prerelease @neo-one/client@prerelease @neo-one/smart-contract@prerelease @neo-one/smart-contract-test@prerelease @neo-one/smart-contract-lib@prerelease @neo-one/smart-contract-typescript-plugin@prerelease ``` -5. Run `yarn neo-one init` or `npx neo-one init` +7. Run `yarn neo-one init` or `npx neo-one init` This command initializes a NEO•ONE project with a `Hello World` smart contract under `neo-one/contracts/HelloWorld.ts`, a unit test under `src/__tests__/HelloWorld.test.ts`, and a config file,`.neo-one.config.ts`. For this tutorial, we will be building a `Token` from the ground up, so you can go ahead and delete the two `HelloWorld` files. We also recommend taking a moment to [setup your editor](/docs/environment-setup#Editor-Setup) to take advantage of inline NEO•ONE compiler diagnostics. -6. Review the available [configuration options](/docs/config-options) and update your `.neo-one.config.ts` file as needed. +8. Review the available [configuration options](/docs/config-options) and update your `.neo-one.config.ts` file as needed. - This tutorial uses the default options. To follow along, nothing needs to be changed. +## Troubleshooting + +You may or may not run into environment problems when using the CLI, trying to test your smart contract, or other NEO•ONE functions that use the NEO•ONE node. The NEO•ONE node now uses the C# NeoVM instead of our own implementation of the NeoVM in TypeScript, which means that NEO•ONE controls C# code through some complicated mechanisms. If you run into problems with running a node (such as when running `neo-one init` or `neo-one build`) then try these steps: + +- Add these environment variables to your shell environment: + - `EDGE_USE_CORECLR=1` + - `EDGE_APP_ROOT=/node_modules/@neo-one/node-vm/lib/Debug/netcoreapp3.0` +- Install `pkgconfig` on macOS with Homebrew: `brew install pkgconfig` + - Then add this environment variable: `PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig` + - You then need to re-install your node modules by deleting the `node_modules` folder and then running `npm install` again +- Try running the NEO•ONE CLI command using `sudo`, such as: `sudo npx neo-one init` + +To see a demonstration of environment setup go to our YouTube channel for helpful videos: https://www.youtube.com/channel/UCya5J1Tt2h-kX-I3a7LOvtw + ### Help, I'm Stuck! If you get stuck, check out the [Help](/docs/getting-started#Help) section. In particular, come chat with us on [Discord](https://discord.gg/S86PqDE), we're more than happy to assist in any way we can. @@ -303,11 +319,9 @@ For those of you that have experience with other NEO Smart Contract languages, y The main difference for the NEO•ONE client APIs is that non-constant methods require relaying a transaction to the blockchain. This makes sense because a non-constant method by definiton mutates storage, and we need to persist those changes to the blockchain. We'll have to wait until the next section to test our `transfer` method since we don't currently have a way of creating tokens. -### Native Asset Methods - -The NEO blockchain supports native assets, the two most important ones being NEO and GAS. Native assets are Unspent Transaction Output (UTXO) based and are understood natively by the blockchain. Contrast this with tokens like the one we've built so far which live entirely in custom smart contracts. As a result, they require special handling within smart contracts. Luckily, NEO•ONE smart contracts abstract most of this away and let you focus on the logic of your smart contract. +### Assets -In order to receive native assets, we can decorate a method with `@receive`. Methods marked with `@receive` must throw an error to indicate if the contract does not want to receive the assets. Note, however, that there are cases where the contract may still receive assets, despite throwing an error, due to limitations in how NEO handles native UTXO assets. For these cases, we automatically generate a `refundAssets` method that clients of your smart contract may call to refund assets which were not processed by the smart contract (i.e. the smart contract threw an error or was not called). Note that this method cannot refund assets if the smart contract invocation succeeded. +All tokens, including native assets NEO and GAS, operate like the one we've built so far which live entirely in custom smart contracts. As a result, they require special handling within smart contracts. Luckily, NEO•ONE smart contracts abstract most of this away and let you focus on the logic of your smart contract. Let's add the `mintTokens` method to our `Token` smart contract to enable minting new tokens. @@ -316,24 +330,19 @@ export class Token extends SmartContract { @receive public mintTokens(): void { // Inspect the current transaction - const { references, outputs } = Blockchain.currentTransaction; - if (references.length === 0) { + const { notifications } = Blockchain.currentTransaction; + if (notifications.length === 0) { throw new Error('Invalid mintTokens'); } // Take the first sender address as the minter. - const sender = references[0].address; + const sender = notifications[0].scriptHash; // Sum up the amount of NEO sent to the contract. If anything else is sent, throw an error. let amount = 0; - for (const output of outputs) { - if (output.address.equals(this.address)) { - if (!output.asset.equals(Hash256.NEO)) { - throw new Error('Invalid mintTokens'); - } - - amount += output.value; - } + for (const notification of notifications) { + // Parse the stack items array in each notification to determine how much the sender transfered + // This is a WIP for our compiler and is coming soon } this.issue(sender, amount); @@ -348,12 +357,12 @@ export class Token extends SmartContract { } ``` -Notice that we access the current transaction using `Blockchain.currentTransaction`. The transaction itself has many useful properties, but for now we are only interested in the `references` and `outputs` properties. The `outputs` defines the destination addresses and amounts for native assets. A reference is the corresponding `output` for the `input`s of the transaction. +Notice that we access the current transaction using `Blockchain.currentTransaction`. The transaction itself has many useful properties, but for now we are only interested in the `notifications` property. The `notifications` defines the notifications produced by the transaction. Each notification will have a `scriptHash` property, an `eventName` property, and a `state` property. We can parse these properties to see what events were triggered by the transaction. In this case we want to see Transfer events that were produced by the NeoToken native contract, which will tell us how much was transfered, from what address, and to what address. Now that we can mint tokens, let's see how we can test both `transfer` and `mintTokens`. Note that any NEO•ONE types necessary in your tests should be imported from `@neo-one/client`: ```typescript -import { Hash256 } from '@neo-one/client'; +import { Hash160 } from '@neo-one/client'; import BigNumber from 'bignumber.js'; ... @@ -368,7 +377,7 @@ await withContracts(async ({ token, accountIDs }) => { sendTo: [ { amount, - asset: Hash256.NEO, + asset: Hash160.NEO, }, ], from: accountID, @@ -411,7 +420,7 @@ Phew, quite a bit, but we're testing a lot of functionality here. Recall that we First, invoke the smart contract method which will return a `Promise`. The `TransactionResult` object contains two properties, `transaction` which is the full transaction object that was relayed to the network, and `confirmed` which is a function we can call to wait for the transaction to be confirmed. -Second, call `confirmed` which returns a `Promise`. This `InvokeReceipt` contains many useful properties, like the `event`s that were emitted during execution as well as the final `result` of the smart contract invocation. To learn more, take a look at the detailed [documentation](/docs/smart-contract-apis#methods) on invoking smart contract methods. Methods marked with `@receive` also take an additional argument for the native assets to send with the invocation. +Second, call `confirmed` which returns a `Promise`. This `InvokeReceipt` contains many useful properties, like the `event`s that were emitted during execution as well as the final `result` of the smart contract invocation. To learn more, take a look at the detailed [documentation](/docs/smart-contract-apis#methods) on invoking smart contract methods. Putting it all together, we see both forms of invoking smart contract methods in the above snippet. When we mint tokens, we use the 2-step form, and when we transfer we use the 1-step or shortcut form.