diff --git a/docs/basics/abi.md b/docs/basics/abi.md deleted file mode 100644 index edfc3e0e..00000000 --- a/docs/basics/abi.md +++ /dev/null @@ -1,95 +0,0 @@ -# Application Binary Interfaces - -When interacting with any application, whether it is on Ethereum, -over the internet or within a compiled application on a computer -all information is stored and sent as binary data which is just a -sequence of bytes. - -So every application must agree on how to encode and decode their -information as a sequence of bytes. - -An **Application Binary Interface** (ABI) provides a way to describe -the encoding and decoding process, in a generic way so that a variety -of types and structures of types can be defined. - -For example, a string is often encoded as a UTF-8 sequence of bytes, -which uses specific bits within sub-sequences to indicate emoji and -other special characters. Every implementation of UTF-8 must understand -and operate under the same rules so that strings work universally. In -this way, UTF-8 standard is itself an ABI. - -When interacting with Ethereum, a contract received a sequence of bytes -as input (provided by sending a transaction or through a call) and -returns a result as a sequence of bytes. So, each Contract has its own -ABI that helps specify how to encode the input and how to decode the output. - -It is up to the contract developer to make this ABI available. Many -Contracts implement a standard (such as ERC-20), in which case the -ABI for that standard can be used. Many developers choose to verify their -source code on quaiscan, in which case quaiscan computes the ABI and -provides it through their website (which can be fetched using the `getContract` -method). Otherwise, beyond reverse engineering the Contract there is -not a meaningful way to extract the contract ABI. - -## Call Data Representation - -When calling a Contract on Ethereum, the input data must be encoded -according to the ABI. - -The first 4 bytes of the data are the **method selector**, which is -the keccak256 hash of the normalized method signature. - -Then the method parameters are encoded and concatenated to the selector. - -All encoded data is made up of components padded to 32 bytes, so the length -of input data will always be congruent to `4 mod 32`. - -The result of a successful call will be encoded values, whose components -are padded to 32 bytes each as well, so the length of a result will always -be congruent to `0 mod 32`, on success. - -The result of a reverted call will contain the **error selector** as the -first 4 bytes, which is the keccak256 of the normalized error signature, -followed by the encoded values, whose components are padded to 32 bytes -each, so the length of a revert will be congruent to `4 mod 32`. - -The one exception to all this is that `revert(false)` will return a -result or `0x`. - -## Event Data Representation - -When an Event is emitted from a contract, there are two places data is -logged in a Log: the **topics** and the **data**. - -An additonal fee is paid for each **topic**, but this affords a topic -to be indexed in a bloom filter within the block, which allows efficient -filtering. - -The **topic hash** is always the first topic in a Log, which is the -keccak256 of the normalized event signature. This allows a specific -event to be efficiently filtered, finding the matching events in a block. - -Each additional **indexed** parameter (i.e. parameters marked with -`indexed` in the signautre) are placed in the topics as well, but may be -filtered to find matching values. - -All non-indexed parameters are encoded and placed in the **data**. This -is cheaper and more compact, but does not allow filtering on these values. - -For example, the event `Transfer(address indexed from, address indexed to, uint value)` -would require 3 topics, which are the topic hash, the `from` address -and the `to` address and the data would contain 32 bytes, which is -the padded big-endian representation of `value`. This allows for -efficient filtering by the event (i.e. `Transfer`) as well as the `from` -address and `to` address. - -## Deployment - -When deploying a transaction, the data provided is treated as **initcode**, -which executes the data as normal EVM bytecode, which returns a sequence -of bytes, but instead of that sequence of bytes being treated as data that -result is instead the bytecode to install as the bytecode of the contract. - -The bytecode produced by Solidity is designed to have all constructor -parameters encoded normally and concatenated to the bytecode and provided -as the `data` to a transaction with no `to` address. \ No newline at end of file diff --git a/docs/basics/index.md b/docs/basics/index.md deleted file mode 100644 index eee3e442..00000000 --- a/docs/basics/index.md +++ /dev/null @@ -1,8 +0,0 @@ -# Quai Basics - -This section aims to cover some of the basics for those interested -in a deeper understanding of the inner-workings of Quai. - -## Topics - -- [Application Binary Interface](docs-abi) \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md index 19a6ddd2..b5c9c2c7 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -2,38 +2,26 @@ Pull requests are welcome, but please keep the following in mind: -- Backwards-compatibility-breaking changes will not be accepted; - they may be considered for the next major version -- Security is important; adding dependencies require fairly - convincing arguments as to why -- The library aims to be lean, so keep an eye on the - `dist/quais.min.js` file size before and after your - changes (the `build-clean` target includes these stats) -- Keep the PR simple, readable and confined to the relevant - files; see below for which files to change -- Add test cases for both expected and unexpected input -- Any new features need to be supported by me (future issues, - documentation, testing, migration), so anything that is - overly complicated or specific may not be accepted -- Everyone is working hard; **be kind and respectful** - -It is always *highly recommended* that you open a [[link-discussion]] -**before** beginning a PR. +- Backwards-compatibility-breaking changes will not be accepted; they may be considered for the next major version +- Security is important; adding dependencies require fairly convincing arguments as to why +- The library aims to be lean, so keep an eye on the `dist/quais.min.js` file size before and after your changes (the `build-clean` target includes these stats) +- Keep the PR simple, readable and confined to the relevant files; see below for which files to change +- Add test cases for both expected and unexpected input +- Any new features need to be supported by me (future issues, documentation, testing, migration), so anything that is overly complicated or specific may not be accepted +- Everyone is working hard; **be kind and respectful** + +It is always _highly recommended_ that you open a [quais Discussion](https://github.com/quais-io/quais.js/discussions) **before** beginning a PR. ## Documentation -The documentation is an area which can always benefit from extra -eyes, extra knowledge and extra examples. +The documentation is an area which can always benefit from extra eyes, extra knowledge and extra examples. -Contributing to the documentation is welcome, but when making -changes to documentation, please ensure that all changes are -made **only** to: +Contributing to the documentation is welcome, but when making changes to documentation, please ensure that all changes are made **only** to: -- Updating `/docs/*\*.md` -- Updating API jsdocs: `/*\* ... */` comment blocks within `/src/` +- Updating `/docs/*\*.md` +- Updating API jsdocs: `/*\* ... */` comment blocks within `/src/` -When adding a new sections, a [[link-discussion]] is -preferred. +When adding a new sections, a [quais Discussion](https://github.com/quais-io/quais.js/discussions) is preferred. All changes should be in the JSdoc format. @@ -41,30 +29,22 @@ All changes should be in the JSdoc format. In general the **only** files you should ever include in a PR are: -- TypeScript source: `/src/*\*.ts` - -Do not include a `package.json` with the updated `tarballHash` -or `version`, and do not include any generated files in your PR. +- TypeScript source: `/src/*\*.ts` -A bug fix **must not** modify anything requiring a minor version -bump (see [[about-contrib-feature]]), such as changing a method -signature or altering the exports. +Do not include a `package.json` with the updated `tarballHash` or `version`, and do not include any generated files in your PR. +A bug fix **must not** modify anything requiring a minor version bump, such as changing a method signature or altering the exports. ### Adding Features -Contributing new features usually require a deeper understanding -of the internal interactions with quais and its components, and -generally requires a minor version bump. +Contributing new features usually require a deeper understanding of the internal interactions with quais and its components, and generally requires a minor version bump. -When making any of the following changes, you must first open a -[[link-discussion]] as the minor version will need to be bumped. +When making any of the following changes, you must first open a [quais Discussion](https://github.com/quais-io/quais.js/discussions) as the minor version will need to be bumped. -- any signature change (such as adding a parameter, changing a - parameter type, changing the return type) -- adding any new export; such as a class, function or constants -- adding any method to any class -- changing any `exports` property within the `package.json` +- any signature change (such as adding a parameter, changing a parameter type, changing the return type) +- adding any new export; such as a class, function or constants +- adding any method to any class +- changing any `exports` property within the `package.json` Changes of this sort should not be made without serious consideration and discussion. diff --git a/docs/cookbook/index.md b/docs/cookbook/index.md deleted file mode 100644 index b190e55d..00000000 --- a/docs/cookbook/index.md +++ /dev/null @@ -1,8 +0,0 @@ -# Cookbook - - -A growing collection of code snippets for common problems and use cases -when developing dapps and other blockchain tools. - -- [Signing Messages and Data](cookbook-signing) -- [React Native Performance](cookbook-react-native) diff --git a/docs/cookbook/react-native.md b/docs/cookbook/react-native.md deleted file mode 100644 index a37e9446..00000000 --- a/docs/cookbook/react-native.md +++ /dev/null @@ -1,34 +0,0 @@ -# React Native - -When using React Native, many of the built-in cryptographic primitives -can be replaced by native, substantially faster implementations. - -This should be available in its own package in the future, but for now -this is highly recommended, and requires installing the -[[link-npm-react-native-quick-crypto]] package. - -```js -import { quais } from "quais"; - -import crypto from "react-native-quick-crypto"; - -quais.randomBytes.register((length) => { - return new Uint8Array(crypto.randomBytes(length)); -}); - -quais.computeHmac.register((algo, key, data) => { - return crypto.createHmac(algo, key).update(data).digest(); -}); - -quais.pbkdf2.register((passwd, salt, iter, keylen, algo) => { - return crypto.pbkdf2Sync(passwd, salt, iter, keylen, algo); -}); - -quais.sha256.register((data) => { - return crypto.createHash('sha256').update(data).digest(); -}); - -quais.sha512.register((data) => { - return crypto.createHash('sha512').update(data).digest(); -}); -``` \ No newline at end of file diff --git a/docs/getting-started.md b/docs/getting-started.md index 27b47dcc..1bb3833b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,9 +1,6 @@ # Getting Started @ @priority<100> -This is a very short introduction to quais, but covers many of the -most common operations that developers require and provides a -starting point for those newer to Quai Network. - +This is a very short introduction to quais, but covers many of the most common operations that developers require and provides a starting point for those newer to Quai Network. ## Getting quais @@ -14,133 +11,92 @@ If using NPM, you must first install quais. /home/test-quais> npm install quais ``` -Everything in quais is exported from its root as well as on the `quais` -object. There are also `exports` in the `package.json` to facilitate -more fine-grained importing. +Everything in quais is exported from its root as well as on the `quais` object. There are also `exports` in the `package.json` to facilitate more fine-grained importing. -Generally this documentation will presume all exports from quais -have been imported in the code examples, but you may import the -necessary objects in any way you wish. +Generally this documentation will presume all exports from quais have been imported in the code examples, but you may import the necessary objects in any way you wish. ```js title=Importing In NodeJS - // Import everything - import { quais } from "quais"; +// Import everything +import { quais } from 'quais'; - // Import just a few select items - import { BrowserProvider, parseUnits } from "quais"; +// Import just a few select items +import { BrowserProvider, parseUnits } from 'quais'; - // Import from a specific export - import { HDNodeWallet } from "quais/wallet"; +// Import from a specific export +import { HDNodeWallet } from 'quais/wallet'; ``` ```js title=Importing In a Browser - + ``` - ## Some Common Terminology -To begin, it is useful to have a basic understanding of the types of -objects available and what they are responsible for, at a high level. +To begin, it is useful to have a basic understanding of the types of objects available and what they are responsible for, at a high level. ### Provider -A [[Provider]] is a read-only connection to the blockchain, which allows -querying the blockchain state, such as account, block or transaction details, -querying event logs or evaluating read-only code using call. +A Provider is a read-only connection to the blockchain, which allows querying the blockchain state, such as account, block or transaction details, querying event logs or evaluating read-only code using call. -If you are coming from Web3.js, you are used to a **Provider** offering -both read and write access. In quais, all write operations are further -abstracted into another Object, the **Signer**. +If you are coming from Web3.js, you are used to a **Provider** offering both read and write access. In quais, all write operations are further abstracted into another Object, the **Signer**. ### Signer -A [[Signer]] wraps all operations that interact with an account. An -account generally has a private key located //somewhere*, which can be -used to sign a variety of types of payloads. +A Signer wraps all operations that interact with an account. An account generally has a private key located //somewhere\*, which can be used to sign a variety of types of payloads. -The private key may be located in memory (using a [[Wallet]]) or -protected via some IPC layer, such as MetaMask which proxies interaction -from a website to a browser plug-in, which keeps the private key out of -the reach of the website and only permits interaction after requesting -permission from the user and receiving authorization. +The private key may be located in memory (using a Wallet) or protected via some IPC layer, such as MetaMask which proxies interaction from a website to a browser plug-in, which keeps the private key out of the reach of the website and only permits interaction after requesting permission from the user and receiving authorization. ### Transaction -To make any state changes to the blockchain, a transaction is required, -which requires a fee to be paid, where the fee covers the associated costs -with executing the transaction (such as reading the disk and performing -maths) and storing the updated information. +To make any state changes to the blockchain, a transaction is required, which requires a fee to be paid, where the fee covers the associated costs with executing the transaction (such as reading the disk and performing maths) and storing the updated information. -If a transaction reverts, a fee must still be paid, since the validator -still had to expend resources to try running the transaction to determine -that it reverted and the details of its failure are still be recorded. +If a transaction reverts, a fee must still be paid, since the validator still had to expend resources to try running the transaction to determine that it reverted and the details of its failure are still be recorded. -Transactions include sending ether from one user to another, deploying -a **Contract** or executing a state-changing operation against a -**Contract**. +Transactions include sending ether from one user to another, deploying a **Contract** or executing a state-changing operation against a **Contract**. ### Contract -A [[Contract]] is a program that has been deployed to the blockchain, -which includes some code and has allocated storage which it can read -from and write to. +A Contract is a program that has been deployed to the blockchain, which includes some code and has allocated storage which it can read from and write to. -It may be read from when it is connected to a [[Provider]] or -state-changing operations can be called when connected to a [[Signer]]. +It may be read from when it is connected to a Provider or state-changing operations can be called when connected to a Signer. ### Receipt -Once a **Transaction** has been submitted to the blockchain, it is placed -in the memory pool (mempool) until a validator decides to include it. - -A transaction's changes are only made once it has been included in the -blockchain, at which time a receipt is available, which includes details -about the transaction, such as which block it was included in, the actual -fee paid, gas used, all the events that it emitted and whether it was -successful or reverted. +Once a **Transaction** has been submitted to the blockchain, it is placed in the memory pool (mempool) until a validator decides to include it. +A transaction's changes are only made once it has been included in the blockchain, at which time a receipt is available, which includes details about the transaction, such as which block it was included in, the actual fee paid, gas used, all the events that it emitted and whether it was successful or reverted. -## Connecting to Ethereum @ +## Connecting to Ethereum @ -This very first thing needed to begin interacting with the blockchain is -connecting to it using a [[Provider]]. +This very first thing needed to begin interacting with the blockchain is connecting to it using a [[Provider]]. ### MetaMask (and other injected providers) -The quickest and easiest way to experiment and begin developing -on Ethereum is to use [[link-metamask]], which is a browser -extension that injects objects into the `window`, providing: +The quickest and easiest way to experiment and begin developing on Ethereum is to use [MetaMask](https://metamask.io/), which is a browser extension that injects objects into the `window`, providing: -- read-only access to the Ethereum network (a [[Provider]]) -- authenticated write access backed by a private key (a [[Signer]]) +- read-only access to the Ethereum network (a Provider) +- authenticated write access backed by a private key (a Signer) -When requesting access to the authenticated methods, such as -sending a transaction or even requesting the private key address, -MetaMask will show a pop-up to the user asking for permission. +When requesting access to the authenticated methods, such as sending a transaction or even requesting the private key address, MetaMask will show a pop-up to the user asking for permission. ```js let signer = null; let provider; if (window.ethereum == null) { - // If MetaMask is not installed, we use the default provider, // which is backed by a variety of third-party services (such // as INFURA). They do not have private keys installed, // so they only have read-only access - console.log("MetaMask not installed; using read-only defaults") - provider = quais.getDefaultProvider() - + console.log('MetaMask not installed; using read-only defaults'); + provider = quais.getDefaultProvider(); } else { - // Connect to the MetaMask EIP-1193 object. This is a standard // protocol that allows quais access to make all read-only // requests through MetaMask. - provider = new quais.BrowserProvider(window.ethereum) + provider = new quais.BrowserProvider(window.ethereum); // It also provides an opportunity to request access to write // operations, which will be performed by the private key @@ -149,115 +105,88 @@ if (window.ethereum == null) { } ``` - ### Custom RPC Backend -If you are running your own Ethereum node (e.g. [[link-geth]]) -or using a custom third-party service (e.g. [[link-infura]]), -you can use the [[JsonRpcProvider]] directly, which communicates -using the [[link-jsonrpc]] protocol. +If you are running your own Ethereum node (e.g. link-geth [Geth](https://geth.ethereum.org)) or using a custom third-party service (e.g. [INFURA](https://infura.io)), you can use the `JsonRpcProvider` directly, which communicates using the [link-jsonrpc](https://github.com/ethereum/wiki/wiki/JSON-RPC) protocol. -When using your own Ethereum node or a developer-base blockchain, -such as Hardhat or Ganache, you can get access to the accounts with -[[JsonRpcProvider-getSigner]]. +When using your own Ethereum node or a developer-base blockchain, such as Hardhat or Ganache, you can get access to the accounts with `JsonRpcProvider-getSigner`. ```js // If no url is provided, it connects to the default // http://localhost:8545, which most nodes use. -provider = new quais.JsonRpcProvider(url) +provider = new quais.JsonRpcProvider(url); // Get write access as an account by getting the signer -signer = await provider.getSigner() +signer = await provider.getSigner(); ``` -## User Interaction +## User Interaction -All units in Ethereum tend to be integer values, since dealing with -decimals and floating points can lead to imprecise and non-obvious -results when performing mathematic operations. +All units in Ethereum tend to be integer values, since dealing with decimals and floating points can lead to imprecise and non-obvious results when performing mathematic operations. -As a result, the internal units used (e.g. wei) which are suited for -machine-readable purposes and maths are often very large and not -easily human-readable. +As a result, the internal units used (e.g. wei) which are suited for machine-readable purposes and maths are often very large and not easily human-readable. -For example, imagine dealing with dollars and cents; you would show -values like `"$2.56"`. In the blockchain world, we would keep all -values as cents, so that would be `256` cents, internally. +For example, imagine dealing with dollars and cents; you would show values like `"$2.56"`. In the blockchain world, we would keep all values as cents, so that would be `256` cents, internally. -So, when accepting data that a user types, it must be converted from -its decimal string representation (e.g. `"2.56"`) to its lowest-unit -integer representation (e.g. `256`). And when displaying a value to -a user the opposite operation is necessary. +So, when accepting data that a user types, it must be converted from its decimal string representation (e.g. `"2.56"`) to its lowest-unit integer representation (e.g. `256`). And when displaying a value to a user the opposite operation is necessary. -In Ethereum, *one ether* is equal to `10 *\* 18` wei and *one gwei* -is equal to `10 *\* 9` wei, so the values get very large very quickly, -so some convenience functions are provided to help convert between -representations. +In Ethereum, _one ether_ is equal to `10 *\* 18` wei and _one gwei_ is equal to `10 *\* 9` wei, so the values get very large very quickly, so some convenience functions are provided to help convert between representations. ```js - // Convert user-provided strings in ether to wei for a value - eth = parseEther("1.0") - //_result: +// Convert user-provided strings in ether to wei for a value +eth = parseEther('1.0'); +//_result: - // Convert user-provided strings in gwei to wei for max base fee - feePerGas = parseUnits("4.5", "gwei") - //_result: +// Convert user-provided strings in gwei to wei for max base fee +feePerGas = parseUnits('4.5', 'gwei'); +//_result: - // Convert a value in wei to a string in ether to display in a UI - formatEther(eth) - //_result: +// Convert a value in wei to a string in ether to display in a UI +formatEther(eth); +//_result: - // Convert a value in wei to a string in gwei to display in a UI - formatUnits(feePerGas, "gwei") - //_result: +// Convert a value in wei to a string in gwei to display in a UI +formatUnits(feePerGas, 'gwei'); +//_result: ``` - -## Interacting with the Blockchain +## Interacting with the Blockchain ### Querying State -Once you have a [[Provider]], you have a read-only connection to -the data on the blockchain. This can be used to query the current -account state, fetch historic logs, look up contract code and so on. +Once you have a Provider, you have a read-only connection to the data on the blockchain. This can be used to query the current account state, fetch historic logs, look up contract code and so on. ```js - //_hide: provider = new InfuraProvider(); +//_hide: provider = new InfuraProvider(); - // Look up the current block number (i.e. height) - await provider.getBlockNumber() - //_result: +// Look up the current block number (i.e. height) +await provider.getBlockNumber(); +//_result: - // Get the current balance of an account - balance = await provider.getBalance("0x643aA0A61eADCC9Cc202D1915D942d35D005400C") - //_result: +// Get the current balance of an account +balance = await provider.getBalance('0x643aA0A61eADCC9Cc202D1915D942d35D005400C'); +//_result: - // Since the balance is in wei, you may wish to display it - // in ether instead. - formatEther(balance) - //_result: +// Since the balance is in wei, you may wish to display it +// in ether instead. +formatEther(balance); +//_result: - // Get the next nonce required to send a transaction - await provider.getTransactionCount("0x643aA0A61eADCC9Cc202D1915D942d35D005400C") - //_result: +// Get the next nonce required to send a transaction +await provider.getTransactionCount('0x643aA0A61eADCC9Cc202D1915D942d35D005400C'); +//_result: ``` ### Sending Transactions -To write to the blockchain you require access to a private key -which controls some account. In most cases, those private keys -are not accessible directly to your code, and instead you make -requests via a [[Signer]], which dispatches the request to a -service (such as [[link-metamask]]) which provides strictly -gated access and requires feedback to the user to approve or -reject operations. +To write to the blockchain you require access to a private key which controls some account. In most cases, those private keys are not accessible directly to your code, and instead you make requests via a [[Signer]], which dispatches the request to a service (such as [MetaMask](https://metamask.io/)) which provides strictly gated access and requires feedback to the user to approve or reject operations. ```js // When sending a transaction, the value is in wei, so parseEther // converts ether to wei. tx = await signer.sendTransaction({ - to: "quais.eth", - value: parseEther("1.0") + to: 'quais.eth', + value: parseEther('1.0'), }); //_result: @@ -266,76 +195,62 @@ receipt = await tx.wait(); //_result: ``` - ## Contracts -A **Contract** is a meta-class, which means that its definition -its derived at run-time, based on the ABI it is passed, which then -determined what methods and properties are available on it. +A **Contract** is a meta-class, which means that its definition its derived at run-time, based on the ABI it is passed, which then determined what methods and properties are available on it. ### Application Binary Interface (ABI) -Since all operations that occur on the blockchain must be encoded -as binary data, we need a concise way to define how to convert -between common objects (like strings and numbers) and its binary -representation, as well as encode the ways to call and interpret -the Contract. +Since all operations that occur on the blockchain must be encoded as binary data, we need a concise way to define how to convert between common objects (like strings and numbers) and its binary representation, as well as encode the ways to call and interpret the Contract. -For any method, event or error you wish to use, you must include a -[[Fragment]] to inform quais how it should encode the request and -decode the result. +For any method, event or error you wish to use, you must include a Fragment to inform quais how it should encode the request and decode the result. Any methods or events that are not needed can be safely excluded. -There are several common formats available to describe an ABI. The -Solidity compiler usually dumps a JSON representation but when typing -an ABI by hand it is often easier (and more readable) to use the -human-readable ABI, which is just the Solidity signature. +There are several common formats available to describe an ABI. The Solidity compiler usually dumps a JSON representation but when typing an ABI by hand it is often easier (and more readable) to use the human-readable ABI, which is just the Solidity signature. ```js - abi = [ - "function decimals() view returns (string)", - "function symbol() view returns (string)", - "function balanceOf(address addr) view returns (uint)" - ] - - // Create a contract - contract = new Contract("0x643aA0A61eADCC9Cc202D1915D942d35D005400C", abi, provider) +abi = [ + 'function decimals() view returns (string)', + 'function symbol() view returns (string)', + 'function balanceOf(address addr) view returns (uint)', +]; + +// Create a contract +contract = new Contract('0x643aA0A61eADCC9Cc202D1915D942d35D005400C', abi, provider); ``` ### Read-only methods (i.e. `view` and `pure`) -A read-only method is one which cannot change the state of the -blockchain, but often provide a simple interface to get important -data about a Contract. +A read-only method is one which cannot change the state of the blockchain, but often provide a simple interface to get important data about a Contract. ```js - // The contract ABI (fragments we care about) - abi = [ - "function decimals() view returns (uint8)", - "function symbol() view returns (string)", - "function balanceOf(address a) view returns (uint)" - ] - - // Create a contract; connected to a Provider, so it may - // only access read-only methods (like view and pure) - contract = new Contract("0x643aA0A61eADCC9Cc202D1915D942d35D005400C", abi, provider) - - // The symbol name for the token - sym = await contract.symbol() - //_result: +// The contract ABI (fragments we care about) +abi = [ + 'function decimals() view returns (uint8)', + 'function symbol() view returns (string)', + 'function balanceOf(address a) view returns (uint)', +]; + +// Create a contract; connected to a Provider, so it may +// only access read-only methods (like view and pure) +contract = new Contract('0x643aA0A61eADCC9Cc202D1915D942d35D005400C', abi, provider); + +// The symbol name for the token +sym = await contract.symbol(); +//_result: - // The number of decimals the token uses - decimals = await contract.decimals() - //_result: +// The number of decimals the token uses +decimals = await contract.decimals(); +//_result: - // Read the token balance for an account - balance = await contract.balanceOf("quais.eth") - //_result: +// Read the token balance for an account +balance = await contract.balanceOf('quais.eth'); +//_result: - // Format the balance for humans, such as in a UI - formatUnits(balance, decimals) - //_result: +// Format the balance for humans, such as in a UI +formatUnits(balance, decimals); +//_result: ``` ### State-changing Methods @@ -389,118 +304,99 @@ _code: forcing a call (simulation) of a state-changing method @lang ### Listening to Events -When adding event listeners for a named event, the event parameters -are destructed for the listener. +When adding event listeners for a named event, the event parameters are destructed for the listener. -There is always one additional parameter passed to a listener, which -is an [[EventPayload]], which includes more information about the event -including the filter and a method to remove that listener. +There is always one additional parameter passed to a listener, which is an `EventPayload`, which includes more information about the event including the filter and a method to remove that listener. ```js title=listen for ERC-20 events - abi = [ - "event Transfer(address indexed from, address indexed to, uint amount)" - ] +abi = ['event Transfer(address indexed from, address indexed to, uint amount)']; - // Create a contract; connected to a Provider, so it may - // only access read-only methods (like view and pure) - contract = new Contract("0x643aA0A61eADCC9Cc202D1915D942d35D005400C", abi, provider) +// Create a contract; connected to a Provider, so it may +// only access read-only methods (like view and pure) +contract = new Contract('0x643aA0A61eADCC9Cc202D1915D942d35D005400C', abi, provider); - // Begin listening for any Transfer event - contract.on("Transfer", (from, to, _amount, event) => { - const amount = formatEther(_amount, 18) - console.log(`${ from } => ${ to }: ${ amount }`); +// Begin listening for any Transfer event +contract.on('Transfer', (from, to, _amount, event) => { + const amount = formatEther(_amount, 18); + console.log(`${from} => ${to}: ${amount}`); // The `event.log` has the entire EventLog // Optionally, stop listening event.removeListener(); - }); +}); - // Same as above - contract.on(contract.filters.Transfer, (from, to, amount, event) => { +// Same as above +contract.on(contract.filters.Transfer, (from, to, amount, event) => { // See above - }) +}); - // Listen for any Transfer to "quais.eth" - filter = contract.filters.Transfer("0x643aA0A61eADCC9Cc202D1915D942d35D005400C") - contract.on(filter, (from, to, amount, event) => { +// Listen for any Transfer to "quais.eth" +filter = contract.filters.Transfer('0x643aA0A61eADCC9Cc202D1915D942d35D005400C'); +contract.on(filter, (from, to, amount, event) => { // `to` will always be equal to the address of "quais.eth" - }); +}); - // Listen for any event, whether it is present in the ABI - // or not. Since unknown events can be picked up, the - // parameters are not destructed. - contract.on("*", (event) => { +// Listen for any event, whether it is present in the ABI +// or not. Since unknown events can be picked up, the +// parameters are not destructed. +contract.on('*', (event) => { // The `event.log` has the entire EventLog - }); +}); ``` ### Query Historic Events -When querying within a large range of blocks, some backends may -be prohibitively slow, may return an error or may truncate the -results without any indication. This is at the discretion of each -backend. +When querying within a large range of blocks, some backends may be prohibitively slow, may return an error or may truncate the results without any indication. This is at the discretion of each backend. -```js title=Query historic ERC-20 events - abi = [ - "event Transfer(address indexed from, address indexed to, uint amount)" - ] +```js title=Query historic ERC-20 events +abi = ['event Transfer(address indexed from, address indexed to, uint amount)']; - // Create a contract; connected to a Provider, so it may - // only access read-only methods (like view and pure) - contract = new Contract("0x643aA0A61eADCC9Cc202D1915D942d35D005400C", abi, provider) +// Create a contract; connected to a Provider, so it may +// only access read-only methods (like view and pure) +contract = new Contract('0x643aA0A61eADCC9Cc202D1915D942d35D005400C', abi, provider); - // Query the last 100 blocks for any transfer - filter = contract.filters.Transfer - events = await contract.queryFilter(filter, -100) +// Query the last 100 blocks for any transfer +filter = contract.filters.Transfer; +events = await contract.queryFilter(filter, -100); - // The events are a normal Array - events.length - //_result: +// The events are a normal Array +events.length; +//_result: - // The first matching event - events[0] - //_result: +// The first matching event +events[0]; +//_result: - // Query all time for any transfer to quais.eth - filter = contract.filters.Transfer("0x643aA0A61eADCC9Cc202D1915D942d35D005400C") - events = await contract.queryFilter(filter) +// Query all time for any transfer to quais.eth +filter = contract.filters.Transfer('0x643aA0A61eADCC9Cc202D1915D942d35D005400C'); +events = await contract.queryFilter(filter); - // The first matching event - events[0] - //_result: +// The first matching event +events[0]; +//_result: ``` - ### Signing Messages -A private key can do a lot more than just sign a transaction to authorize -it. It can also be used to sign other forms of data, which are then able -to be validated for other purposes. +A private key can do a lot more than just sign a transaction to authorize it. It can also be used to sign other forms of data, which are then able to be validated for other purposes. -For example, signing **a message** can be used to prove ownership of an -account which a website could use to authenticate a user and log them in. +For example, signing **a message** can be used to prove ownership of an account which a website could use to authenticate a user and log them in. ```js - // Our signer; Signing messages does not require a Provider - signer = new Wallet(id("test")) - //_result: - - message = "sign into quais.org?" +// Our signer; Signing messages does not require a Provider +signer = new Wallet(id('test')); +//_result: - // Signing the message - sig = await signer.signMessage(message); - //_result: +message = 'sign into quais.org?'; - // Validating a message; notice the address matches the signer - verifyMessage(message, sig) - //_result: +// Signing the message +sig = await signer.signMessage(message); +//_result: +// Validating a message; notice the address matches the signer +verifyMessage(message, sig); +//_result: ``` -Many other more advanced protocols built on top of signed messages are -used to allow a private key to authorize other users to transfer their -tokens, allowing the transaction fees of the transfer to be paid by -someone else. - +Many other more advanced protocols built on top of signed messages are used to allow a private key to authorize other users to transfer their tokens, allowing the transaction fees of the transfer to be paid by someone else. diff --git a/docs/index.md b/docs/index.md index 7616b050..a9b7a020 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,28 +1,11 @@ # Documentation -The quais.js library aims to be a complete and compact library -for interacting with the Ethereum Blockchain and its ecosystem. +The quais.js library aims to be a complete and compact library for interacting with the Ethereum Blockchain and its ecosystem. -It is often used to create decentralized applications (dapps), -wallets (such as [[link-metamask]] and [[link-tally]]) and -other tools and simple scripts that require reading and writing -to the blockchain. +It is often used to create decentralized applications (dapps), wallets (such as [MetaMask](https://metamask.io/) and [Tally](https://tallyho.org)) and other tools and simple scripts that require reading and writing to the blockchain. +## About this documentation? -_subsection: About this documentation? +These docs are still under construction, and are being expanded every day. -These docs are still under construction, and are being expanded -every day. - -Developers new to quais should be sure to read through the -[[getting-started]] section. - -And the [[about-api]] is available for drilling down into more details -about the entire Application Programming Interface. - - -_subsection: Older Documentation - -- [v5 documentation](link-docs-v5) -- [v4 documentation](link-docs-v4) -- [v3 documentation](link-docs-v3) +Developers new to quais should be sure to read through the getting-started section. diff --git a/docs/links/javascript.txt b/docs/links/javascript.txt deleted file mode 100644 index 5434eb71..00000000 --- a/docs/links/javascript.txt +++ /dev/null @@ -1,8 +0,0 @@ -link-js-array [link-js-array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) -link-js-bigint [link-js-bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) -link-js-date [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) -link-js-fetch [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) -link-js-normalize [String.normalize](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize) -link-js-maxsafe [link-js-maxsafe](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER#Description) -link-js-proxy [link-js-proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) -link-js-typedarray [link-js-typedarray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) diff --git a/docs/links/npm.txt b/docs/links/npm.txt deleted file mode 100644 index 4f214133..00000000 --- a/docs/links/npm.txt +++ /dev/null @@ -1,5 +0,0 @@ -link-npm-quais [link-quais-npm](https://www.npmjs.com/search?q=%40quaisproject%2F) -link-npm-events [EventEmitter](https://nodejs.org/dist/latest-v13.x/docs/api/events.html#events_class_eventemitter) -link-npm-query-bignumber [link-npm-query-bignumber](https://www.npmjs.com/search?q=bignumber) -link-npm-react-native-get-random-values [React Native get-random-values](https://www.npmjs.com/package/react-native-get-random-values) -link-npm-react-native-quick-crypto [Quick Crypto](https://www.npmjs.com/package/react-native-quick-crypto) diff --git a/docs/links/projects.txt b/docs/links/projects.txt deleted file mode 100644 index 82583226..00000000 --- a/docs/links/projects.txt +++ /dev/null @@ -1,48 +0,0 @@ -link-alchemy [Alchemy](https://alchemy.com/?a=quais) -link-ankr [Ankr](https://www.ankr.com) -link-cloudflare [Cloudflare](https://developers.cloudflare.com/distributed-web/ethereum-gateway/) -link-ethereum [Ethereum](https://ethereumorg) -link-quaiscan [quaiscan](https://quaiscan.io) -link-expo [Expo](https://expo.io) -link-quaiscan-api [quaiscan API](https://quaiscan.io/apis) -link-flatworm [Flatworm](https://github.com/ricmoo/flatworm) -link-geth [Geth](https://geth.ethereum.org) -link-infura [INFURA](https://infura.io) -link-javascriptcore [JavaScriptCore](https://developer.apple.com/documentation/javascriptcore?language=objc) -link-ledger [Ledger](https://www.ledger.com) -link-metamask [MetaMask](https://metamask.io/) -link-node [Node.js](https://nodejs.org/) -link-otto [Otto](https://github.com/robertkrimen/otto) -link-parity [Parity](https://www.parity.io) -link-pocket [Pocket Network](https://pokt.network) -link-quicknode [QuickNode](https://www.quicknode.com/quais) -link-react-native [React Native](https://reactnative.dev) -link-semver [semver](https://semver.org) -link-solidity [Solidity](https://solidity.readthedocs.io/) -link-tally [Tally](https://tallyho.org) - -# Project-specific -link-alchemy-signup [Alchemy Signup](https://dashboard.alchemyapi.io/signup?referral=55a35117-028e-4b7c-9e47-e275ad0acc6d) -link-ankr-public [link-ankr-public](https://www.ankr.com/protocol/public/) -link-ankr-signup [link-ankr-premium](https://www.ankr.com/protocol/plan/) -link-quaiscan-signup [quaiscan Signup](https://quaiscan.io/apis) -link-quaiscan-ratelimit [link-quaiscan-ratelimit](https://info.quaiscan.com/api-return-errors/) -link-infura-signup [INFURA Signup](https://infura.io/register) -link-geth-debug [link-geth-debug](https://github.com/ethereum/go-ethereum/wiki/Management-APIs#debug) -link-geth-rpc [link-geth-rpc](https://github.com/ethereum/go-ethereum/wiki/Management-APIs) -link-infura-secret [link-infura-secret](https://infura.io/docs/gettingStarted/authentication) -link-parity-trace [link-parity-trace](https://openethereum.github.io/wiki/JSONRPC-trace-module) -link-parity-rpc [link-parity-rpc](https://openethereum.github.io/wiki/JSONRPC) -link-pocket-signup [link-pocket-signup](https://pokt.network/pocket-gateway-ethereum-mainnet/) -link-web3js [link-web3](https://github.com/ethereum/web3.js) -link-web3-http [link-web3-http](https://github.com/ethereum/web3.js/tree/1.x/packages/web3-providers-http) -link-web3-ipc [link-web3-ipc](https://github.com/ethereum/web3.js/tree/1.x/packages/web3-providers-ipc) -link-web3-send [link-web3-send](https://github.com/ethereum/web3.js/blob/1.x/packages/web3-providers-http/types/index.d.ts#L57) -link-web3-ws [link-web3-ws](https://github.com/ethereum/web3.js/tree/1.x/packages/web3-providers-ws) - -link-solidity-errors [link-solidity-errors](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#errors) -link-solidity-events [link-solidity-events](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#events) - -link-other-ethereum-dev-docs [link-other-ethereum-dev-docs](https://ethereum.org/en/developers/docs/) - -link-sol-recovermessage [RecoverMessage.sol](https://sepolia.quaiscan.io/address/0xf554da5e35b2e40c09ddb481545a395da1736513#code) diff --git a/docs/links/ricmoo.txt b/docs/links/ricmoo.txt deleted file mode 100644 index 76708d58..00000000 --- a/docs/links/ricmoo.txt +++ /dev/null @@ -1,21 +0,0 @@ -link-mail [me@ricmoo](mailto:me@ricmoo.com) -link-website [quais.org](https://quais.org) - -# quais links -link-ci [quais CI](https://github.com/quais-io/quais.js/actions/runs/158006903) -link-discussion [quais Discussion](https://github.com/quais-io/quais.js/discussions) -link-issue [Open quais Issue](https://github.com/quais-io/quais.js/issues/new/choose) -link-issues [quais Issues](https://github.com/quais-io/quais.js/issues) -link-docs-v3 [V3 Documentation](https://docs.quais.org/v3/) -link-docs-v4 [V4 Documentation](https://docs.quais.org/v4/) -link-docs-v5 [V5 Documentation](https://docs.quais.org/v5/) - -# Social profiles -link-repo [GitHub Repo](https://github.com/quais-io/quais.js) -link-mastodon [@quais on Mastodon](http://mochi.social/@quais) -link-twitter [@quaisproject on Twitter](https://twitter.com/quaisproject) - -# Blog -link-ricmoo-humanreadableabi [Human-Readable Contract ABIs](https://blog.ricmoo.com/human-readable-contract-abis-in-quais-js-141902f4d917) -link-ricmoo-wisps [Wisps: The Magical World of Create2](https://blog.ricmoo.com/wisps-the-magical-world-of-create2-5c2177027604); - diff --git a/docs/links/specs.txt b/docs/links/specs.txt deleted file mode 100644 index d5a03f3c..00000000 --- a/docs/links/specs.txt +++ /dev/null @@ -1,49 +0,0 @@ -# BIPs -link-bip-39 [BIP-39](https://en.bitcoin.it/wiki/BIP_0039) -link-bip-32 [BIP-32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) -link-bip-44 [BIP-44](https://en.bitcoin.it/wiki/BIP_0044) - -# BIP 39 lists -link-bip39-wordlists [BIP-39 Wordlists](https://github.com/bitcoin/bips/blob/master/bip-0039/bip-0039-wordlists.md) -link-bip39-cz [Czech wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/czech.txt) -link-bip39-es [Spanish wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/spanish.txt) -link-bip39-en [English wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt) -link-bip39-fr [French wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/french.txt) -link-bip39-it [Italian wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/italian.txt) -link-bip39-ja [Japanese wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/japanese.txt) -link-bip39-ko [Korean wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/korean.txt) -link-bip39-pt [Portuguese wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/portuguese.txt) -link-bip39-zh_tw [Tradional Chinese wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/chinese_traditional.txt) -link-bip39-zh_cn [Simplified Chinese wordlist](https://github.com/bitcoin/bips/blob/master/bip-0039/chinese_simplified.txt) - -# EIPs; see https://eips.ethereum.org/all -link-eip-155 [EIP-155](https://eips.ethereum.org/EIPS/eip-155) -link-eip-191 [EIP-191](https://eips.ethereum.org/EIPS/eip-191) -link-eip-609 [EIP-609](https://eips.ethereum.org/EIPS/eip-609) -link-eip-634 [EIP-634](https://eips.ethereum.org/EIPS/eip-634) -link-eip-712 [EIP-712](https://eips.ethereum.org/EIPS/eip-712) -link-eip-1014 [EIP-1014](https://eips.ethereum.org/EIPS/eip-1014) -link-eip-1193 [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) -link-eip-1559 [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) -link-eip-1577 [EIP-1577](https://eips.ethereum.org/EIPS/eip-1577) -link-eip-2070 [EIP-2930](https://eips.ethereum.org/EIPS/eip-2070) -link-eip-2098 [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098) -link-eip-2304 [EIP-2304](https://eips.ethereum.org/EIPS/eip-2304) -link-eip-2718 [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) -link-eip-2930 [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) - -# Open Standards -link-base58 [Base58](https://en.bitcoinwiki.org/wiki/Base58) -link-cors [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) -link-jsonrpc [link-jsonrpc](https://github.com/ethereum/wiki/wiki/JSON-RPC) -link-mit [MIT License](https://en.m.wikipedia.org/wiki/MIT_License) -link-rlp [Recursive-Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/) -link-pbkdf2 [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) -link-solc-abi [ABI Specification](https://docs.soliditylang.org/en/v0.8.19/abi-spec.html#formal-specification-of-the-encoding) -link-solc-jsonabi [ABI JSON Specification](https://docs.soliditylang.org/en/v0.8.19/abi-spec.html#json) -link-solc-errors [Solidity Custom Errors](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#errors) -link-solc-events [Solidity Events](https://docs.soliditylang.org/en/v0.8.4/abi-spec.html#events) -link-solc-output [solc standard output](https://solidity.readthedocs.io/en/v0.6.0/using-the-compiler.html#output-description) -link-solc-packed [Non-Standard Packed Mode](https://docs.soliditylang.org/en/v0.8.14/abi-spec.html#non-standard-packed-mode) -link-uuid [UUID](https://www.ietf.org/rfc/rfc4122.txt) - diff --git a/docs/links/wiki.txt b/docs/links/wiki.txt deleted file mode 100644 index 2e968f50..00000000 --- a/docs/links/wiki.txt +++ /dev/null @@ -1,29 +0,0 @@ -link-wiki-base64 [Base64](https://en.wikipedia.org/wiki/Base64) -link-wiki-basicauth [Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) -link-wiki-backoff [Exponential Backoff](https://en.wikipedia.org/wiki/Exponential_backoff) -link-wiki-bloomfilter [Bloom Filter](https://en.wikipedia.org/wiki/Bloom_filter) -link-wiki-bruteforce [link-wiki-bruteforce](https://en.wikipedia.org/wiki/Brute-force_attack) -link-wiki-cryptographichash [link-wiki-cryptographichash](https://en.wikipedia.org/wiki/Cryptographic_hash_function) -link-wiki-csrf [link-wiki-csrf](https://en.wikipedia.org/wiki/Cross-site_request_forgery) -link-wiki-ecdh [ECDH](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie-Hellman) -link-wiki-ecrecover [ECDSA Public Key Recovery](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Public_key_recovery) -link-wiki-homoglyph [link-wiki-homoglyph](https://en.wikipedia.org/wiki/IDN_homograph_attack) -link-wiki-hmac [link-wiki-hmac](https://en.wikipedia.org/wiki/HMAC) -link-wiki-iban [link-wiki-iban](https://en.wikipedia.org/wiki/International_Bank_Account_Number) -link-wiki-ieee754 [link-wiki-ieee754](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) -link-wiki-iso639 [ISO 639-1 Codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) -link-wiki-observer-pattern [Observer Pattern](https://en.wikipedia.org/wiki/Observer_pattern) -link-wiki-phishing [link-wiki-phishing](https://en.wikipedia.org/wiki/Phishing) -link-wiki-ripemd [link-wiki-ripemd](https://en.m.wikipedia.org/wiki/RIPEMD) -link-wiki-sha2 [link-wiki-sha2](https://en.wikipedia.org/wiki/SHA-2) -link-wiki-twoscomplement [link-wiki-twoscomplement](https://en.wikipedia.org/wiki/Two%27s_complement) -link-wiki-unicode-equivalence [link-wiki-unicode-equivalence](https://en.wikipedia.org/wiki/Unicode_equivalence) -link-wiki-utf8-overlong [link-wiki-utf8-overlong](https://en.wikipedia.org/wiki/UTF-8#Overlong_encodings) -link-wiki-utf8-replacement [link-wiki-utf8-replacement](https://en.wikipedia.org/wiki/Specials_%28Unicode_block%29#Replacement_character) -link-wiki-scrypt [scrypt PBKDF](https://en.wikipedia.org/wiki/Scrypt) -link-wiki-side-channel-attack [link-wiki-side-channel-attack](https://en.wikipedia.org/wiki/Side-channel_attack) -link-wiki-sha3 [link-wiki-sha3](https://en.wikipedia.org/wiki/SHA-3) -link-wiki-shuffle [Fisher-Yates Shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle) -link-wiki-overflow [overflow](https://en.wikipedia.org/wiki/Integer_overflow) -link-wiki-underflow [arithmetic underflow](https://en.wikipedia.org/wiki/Arithmetic_underflow) -link-wiki-xss [link-wiki-xss](https://en.wikipedia.org/wiki/Cross-site_scripting) diff --git a/docs/static/abi.mdx b/docs/static/abi.mdx index 9256d68d..01c7ca34 100644 --- a/docs/static/abi.mdx +++ b/docs/static/abi.mdx @@ -1,4 +1,52 @@ --- -title: Application Binary Interface +title: Application Binary Interfaces description: 'Implement smart contracts through their Application Binary Interface (ABI).' ---- \ No newline at end of file +--- + +When interacting with any application, whether it is on Quai Network, over the internet or within a compiled application on a computer all information is stored and sent as binary data which is just a sequence of bytes. + +So every application must agree on how to encode and decode their information as a sequence of bytes. + +An **Application Binary Interface** (ABI) provides a way to describe the encoding and decoding process, in a generic way so that a variety of types and structures of types can be defined. + +For example, a string is often encoded as a UTF-8 sequence of bytes, which uses specific bits within sub-sequences to indicate emoji and other special characters. Every implementation of UTF-8 must understand and operate under the same rules so that strings work universally. In this way, UTF-8 standard is itself an ABI. + +When interacting with Ethereum, a contract received a sequence of bytes as input (provided by sending a transaction or through a call) and returns a result as a sequence of bytes. So, each Contract has its own ABI that helps specify how to encode the input and how to decode the output. + +It is up to the contract developer to make this ABI available. Many Contracts implement a standard (such as ERC-20), in which case the ABI for that standard can be used. Many developers choose to verify their source code on quaiscan, in which case quaiscan computes the ABI and provides it through their website (which can be fetched using the `getContract` method). Otherwise, beyond reverse engineering the Contract there is not a meaningful way to extract the contract ABI. + +## Call Data Representation + +When calling a Contract on Quai, the input data must be encoded according to the ABI. + +The first 4 bytes of the data are the **method selector**, which isthe keccak256 hash of the normalized method signature. + +Then the method parameters are encoded and concatenated to the selector. + +All encoded data is made up of components padded to 32 bytes, so the length of input data will always be congruent to `4 mod 32`. + +The result of a successful call will be encoded values, whose components are padded to 32 bytes each as well, so the length of a result will always be congruent to `0 mod 32`, on success. + +The result of a reverted call will contain the **error selector** as the first 4 bytes, which is the keccak256 of the normalized error signature, followed by the encoded values, whose components are padded to 32 bytes each, so the length of a revert will be congruent to `4 mod 32`. + +The one exception to all this is that `revert(false)` will return aresult or `0x`. + +## Event Data Representation + +When an Event is emitted from a contract, there are two places data is logged in a Log: the **topics** and the **data**. + +An additonal fee is paid for each **topic**, but this affords a topic to be indexed in a bloom filter within the block, which allows efficient filtering. + +The **topic hash** is always the first topic in a Log, which is the keccak256 of the normalized event signature. This allows a specific event to be efficiently filtered, finding the matching events in a block. + +Each additional **indexed** parameter (i.e. parameters marked with `indexed` in the signautre) are placed in the topics as well, but may be filtered to find matching values. + +All non-indexed parameters are encoded and placed in the **data**. This is cheaper and more compact, but does not allow filtering on these values. + +For example, the event `Transfer(address indexed from, address indexed to, uint value)` would require 3 topics, which are the topic hash, the `from` address and the `to` address and the data would contain 32 bytes, which is the padded big-endian representation of `value`. This allows for efficient filtering by the event (i.e. `Transfer`) as well as the `from` address and `to` address. + +## Deployment + +When deploying a transaction, the data provided is treated as **initcode**, which executes the data as normal EVM bytecode, which returns a sequence of bytes, but instead of that sequence of bytes being treated as data that result is instead the bytecode to install as the bytecode of the contract. + +The bytecode produced by Solidity is designed to have all constructor parameters encoded normally and concatenated to the bytecode and provided as the `data` to a transaction with no `to` address. diff --git a/docs/static/cookbook/react-native.md b/docs/static/cookbook/react-native.md new file mode 100644 index 00000000..a60dd9f7 --- /dev/null +++ b/docs/static/cookbook/react-native.md @@ -0,0 +1,31 @@ +# React Native + +When using React Native, many of the built-in cryptographic primitives can be replaced by native, substantially faster implementations. + +This should be available in its own package in the future, but for now this is highly recommended, and requires installing the [Quick Crypto](https://www.npmjs.com/package/react-native-quick-crypto) package. + +```js +import { quais } from 'quais'; + +import crypto from 'react-native-quick-crypto'; + +quais.randomBytes.register((length) => { + return new Uint8Array(crypto.randomBytes(length)); +}); + +quais.computeHmac.register((algo, key, data) => { + return crypto.createHmac(algo, key).update(data).digest(); +}); + +quais.pbkdf2.register((passwd, salt, iter, keylen, algo) => { + return crypto.pbkdf2Sync(passwd, salt, iter, keylen, algo); +}); + +quais.sha256.register((data) => { + return crypto.createHash('sha256').update(data).digest(); +}); + +quais.sha512.register((data) => { + return crypto.createHash('sha512').update(data).digest(); +}); +``` diff --git a/docs/cookbook/signing.md b/docs/static/cookbook/signing.md similarity index 62% rename from docs/cookbook/signing.md rename to docs/static/cookbook/signing.md index a2476f49..73280145 100644 --- a/docs/cookbook/signing.md +++ b/docs/static/cookbook/signing.md @@ -1,83 +1,49 @@ # Signing -Signing content and providing the content and signature to a -Contract allows on-chain validation that a signer has access -to the private key of a specific address. - -The ecrecover algorithm allows the public key to be determined -given some message digest and the signature generated by the -private key for that digest. From the public key, the address -can then be computed. - -How a digest is derived depends on the type of data being -signed and a variety of encoding formats are employed. Each -format is designed to ensure that they do not collide, so for -example, a user **cannot** be tricked into signing a message -which is actually a valid transaction. - -For this reason, most APIs in Ethereum do not permit signing a -raw digest, and instead require a separate API for each format -type and require the related data be specified, protecting the -user from accidentally authorizing an action they didn't intend. +Signing content and providing the content and signature to a Contract allows on-chain validation that a signer has access to the private key of a specific address. -## Messages +The ecrecover algorithm allows the public key to be determined given some message digest and the signature generated by the private key for that digest. From the public key, the address can then be computed. + +How a digest is derived depends on the type of data being signed and a variety of encoding formats are employed. Each format is designed to ensure that they do not collide, so for example, a user **cannot** be tricked into signing a message which is actually a valid transaction. -A signed message can be any data, but it is generally recommended -to use human-readable text, as this is easier for a user to -verify visually. +For this reason, most APIs in Ethereum do not permit signing a raw digest, and instead require a separate API for each format type and require the related data be specified, protecting the user from accidentally authorizing an action they didn't intend. -This technique could be used, for example, to sign into a service -by using the text `"I am signing into quais.org on 2023-06-04 12:57pm"`. -The user can then see the message in MetaMask or on a Ledger -Hardware Wallet and accept that they wish to sign the message which -the site can then authenticate them with. By providing a timestamp -the site can ensure that an older signed message cannot be used again -in the future. +## Messages -The format that is signed uses [[link-eip-191]] with the -**personal sign** version code (`0x45`, or `"E"`). +A signed message can be any data, but it is generally recommended to use human-readable text, as this is easier for a user to verify visually. -For those interested in the choice of this prefix, signed messages -began as a Bitcoin feature, which used `"\\x18Bitcoin Signed Message:\\n"`, -which was a Bitcoin var-int length-prefixed string (as `0x18` is 24, -the length of `"Bitcoin Signed Message:\\n"`.). When Ethereum adopted -the similar feature, the relevant string was `"\\x19Ethereum Signed Message:\\n"`. +This technique could be used, for example, to sign into a service by using the text `"I am signing into quais.org on 2023-06-04 12:57pm"`. The user can then see the message in MetaMask or on a Ledger Hardware Wallet and accept that they wish to sign the message which the site can then authenticate them with. By providing a timestamp the site can ensure that an older signed message cannot be used again in the future. -In one of the most brilliant instances of technical retcon-ing, -since 0x19 is invalid as the first byte of a transaction (in [[link-rlp]] it -indicates a single byte of value 25), the initial byte `\\x19` has -now been adopted as a prefix for //some sort of signed data//, -where the second byte determines how to interpret that data. If the -second byte is 69 (the letter `"E"`, as in -`"Ethereum Signed Message:\\n"`), then the format is a -the above prefixed message format. +The format that is signed uses [EIP-191](https://eips.ethereum.org/EIPS/eip-191) with the **personal sign** version code (`0x45`, or `"E"`). -So, all existing messages, tools and instances using the signed -message format were already EIP-191 compliant, long before the -standard existed or was even conceived and allowed for an extensible -format for future formats (of which there now a few). +For those interested in the choice of this prefix, signed messages began as a Bitcoin feature, which used `"\\x18Bitcoin Signed Message:\\n"`, which was a Bitcoin var-int length-prefixed string (as `0x18` is 24, the length of `"Bitcoin Signed Message:\\n"`.). When Ethereum adopted the similar feature, the relevant string was `"\\x19Ethereum Signed Message:\\n"`. -Anyways, the necessary JavaScript and Solidity are provided below. +In one of the most brilliant instances of technical retcon-ing, since 0x19 is invalid as the first byte of a transaction (in [Recursive-Length Prefix](https://ethereum.org/en/developers/docs data-structures-and-encoding/rlp/) it indicates a single byte of value 25), the initial byte `\\x19` has now been adopted as a prefix for //some sort of signed data//, where the second byte determines how to interpret that data. If the second byte is 69 (the letter `"E"`, as in `"Ethereum Signed Message:\\n"`), then the format is a the above prefixed message format. +So, all existing messages, tools and instances using the signed message format were already EIP-191 compliant, long before the standard existed or was even conceived and allowed for an extensible format for future formats (of which there now a few). ```js // The contract below is deployed to Sepolia at this address -contractAddress = "0xf554DA5e35b2e40C09DDB481545A395da1736513"; -contract = new Contract(contractAddress, [ - "function recoverStringFromCompact(string message, (bytes32 r, bytes32 yParityAndS) sig) pure returns (address)", - "function recoverStringFromExpanded(string message, (uint8 v, bytes32 r, bytes32 s) sig) pure returns (address)", - "function recoverStringFromVRS(string message, uint8 v, bytes32 r, bytes32 s) pure returns (address)", - "function recoverStringFromRaw(string message, bytes sig) pure returns (address)", - "function recoverHashFromCompact(bytes32 hash, (bytes32 r, bytes32 yParityAndS) sig) pure returns (address)" -], new quais.InfuraProvider("sepolia")); +contractAddress = '0xf554DA5e35b2e40C09DDB481545A395da1736513'; +contract = new Contract( + contractAddress, + [ + 'function recoverStringFromCompact(string message, (bytes32 r, bytes32 yParityAndS) sig) pure returns (address)', + 'function recoverStringFromExpanded(string message, (uint8 v, bytes32 r, bytes32 s) sig) pure returns (address)', + 'function recoverStringFromVRS(string message, uint8 v, bytes32 r, bytes32 s) pure returns (address)', + 'function recoverStringFromRaw(string message, bytes sig) pure returns (address)', + 'function recoverHashFromCompact(bytes32 hash, (bytes32 r, bytes32 yParityAndS) sig) pure returns (address)', + ], + new quais.InfuraProvider('sepolia'), +); // The Signer; it does not need to be connected to a Provider to sign -signer = new Wallet(id("foobar")); -signer.address +signer = new Wallet(id('foobar')); +signer.address; //_result: // Our message -message = "Hello World"; +message = 'Hello World'; // The raw signature; 65 bytes rawSig = await signer.signMessage(message); @@ -88,7 +54,6 @@ rawSig = await signer.signMessage(message); sig = Signature.from(rawSig); //_result: - // If the signature matches the EIP-2098 format, a Signature // can be passed as the struct value directly, since the // parser will pull out the matching struct keys from sig. @@ -112,14 +77,9 @@ await contract.recoverStringFromRaw(message, rawSig); // Note: The above recovered addresses matches the signer address ``` -The Solidity Contract has been deployed and verified on -the Sepolia testnet at the address -[0xf554DA5e35b2e40C09DDB481545A395da1736513](link-sol-recovermessage). - -It provides a variety of examples using various Signature -encodings and formats, to recover the address for an [[link-eip-191]] -signed message. +The Solidity Contract has been deployed and verified on the Sepolia testnet at the address [0xf554DA5e35b2e40C09DDB481545A395da1736513](https://sepolia.quaiscan.io/address/0xf554da5e35b2e40c09ddb481545a395da1736513#code). +It provides a variety of examples using various Signature encodings and formats, to recover the address for an [EIP-191](https://eips.ethereum.org/EIPS/eip-191) signed message. ```solidity // SPDX-License-Identifier: MIT @@ -225,7 +185,7 @@ contract RecoverMessage { // When using raw signatures, some tools return the v as 0 or 1. In this case you must // add 27 to that value as v must be either 27 or 28. // - // This Signature format is 65 bytes of data, but when ABI encoded is 160 bytes in length; + // This Signature format is 65 bytes of data, but when ABI encoded is 160 bytes in length; // a pointer (32 bytes), a length (32 bytes) and the padded 3 words of data (96 bytes). function recoverStringFromRaw(string calldata message, bytes calldata sig) public pure returns (address) { @@ -265,4 +225,4 @@ contract RecoverMessage { return ecrecover(digest, v, sig.r, s); } } -``` \ No newline at end of file +```