diff --git a/blog/2021-11-16-connect-to-metamask.md b/blog/2021-11-16-connect-to-metamask.md index 950a405198..c1a37631ae 100644 --- a/blog/2021-11-16-connect-to-metamask.md +++ b/blog/2021-11-16-connect-to-metamask.md @@ -18,7 +18,7 @@ This post uses a live code editor. Check out [this post](2021-11-15-code-playgro :::tip -Make sure that you have have [Metamask installed](https://metamask.io) in your browser. +Make sure that you have have [Metamask installed](https://metamask.io) in your browser. ::: @@ -33,13 +33,12 @@ This function will only trigger an action if Metamask is not yet connect to the ::: ```jsx live -function connect(){ +function connect() { + function connectMetamask() { + ethereum.request({ method: "eth_requestAccounts" }); + } - function connectMetamask(){ - ethereum.request({ method: 'eth_requestAccounts' }) - } - - return + return ; } ``` @@ -52,51 +51,52 @@ This example shows how you can prompt a user to connect to a specific Celo netwo Try it out: ```jsx live -function MetamaskSwitchNetwork(){ - - const NETWORK_PARAMS = { - chainName: 'Celo', - nativeCurrency: { - name: 'Celo', - symbol: 'CELO', - decimals: 18 - } - } - - const MAINNET_PARAMS = { - ...NETWORK_PARAMS, - chainId: '0xa4ec', // 42220 - rpcUrls: ['https://forno.celo.org'], - blockExplorerUrls: ['https://explorer.celo.org/'] - } - - const ALFAJORES_PARAMS = { - ...NETWORK_PARAMS, - chainId: '0xaef3', // 44787 - rpcUrls: ['https://alfajores-forno.celo-testnet.org'], - blockExplorerUrls: ['https://alfajores-blockscout.celo-testnet.org/'] - } - - function addMainnet(){ - window.ethereum.request({ - method: 'wallet_addEthereumChain', - params: [MAINNET_PARAMS], - }); - } - - function addAlfajores(){ - window.ethereum.request({ - method: 'wallet_addEthereumChain', - params: [ALFAJORES_PARAMS], - }); - } - - return ( -
-
-
-
- ) +function MetamaskSwitchNetwork() { + const NETWORK_PARAMS = { + chainName: "Celo", + nativeCurrency: { + name: "Celo", + symbol: "CELO", + decimals: 18, + }, + }; + + const MAINNET_PARAMS = { + ...NETWORK_PARAMS, + chainId: "0xa4ec", // 42220 + rpcUrls: ["https://forno.celo.org"], + blockExplorerUrls: ["https://explorer.celo.org/"], + }; + + const ALFAJORES_PARAMS = { + ...NETWORK_PARAMS, + chainId: "0xaef3", // 44787 + rpcUrls: ["https://alfajores-forno.celo-testnet.org"], + blockExplorerUrls: ["https://alfajores-blockscout.celo-testnet.org/"], + }; + + function addMainnet() { + window.ethereum.request({ + method: "wallet_addEthereumChain", + params: [MAINNET_PARAMS], + }); + } + + function addAlfajores() { + window.ethereum.request({ + method: "wallet_addEthereumChain", + params: [ALFAJORES_PARAMS], + }); + } + + return ( +
+ +
+ +
+
+ ); } ``` @@ -105,24 +105,24 @@ function MetamaskSwitchNetwork(){ The following code example shows how you can add the cUSD token on the Alfajores testnet to Metamask. To add other tokens, just update the parameter options. You can read more about the Metamask API [here](https://docs.metamask.io/guide/rpc-api.html#wallet-watchasset). ```jsx live -function MetamaskAddToken(){ - const TOKEN_PARAMS = { - type: 'ERC20', - options: { - address: '0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1', - symbol: 'cUSD', - decimals: 18 - } - } - - function addToken(){ - window.ethereum.request({ - method: 'wallet_watchAsset', - params: TOKEN_PARAMS - }); - } - - return +function MetamaskAddToken() { + const TOKEN_PARAMS = { + type: "ERC20", + options: { + address: "0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1", + symbol: "cUSD", + decimals: 18, + }, + }; + + function addToken() { + window.ethereum.request({ + method: "wallet_watchAsset", + params: TOKEN_PARAMS, + }); + } + + return ; } ``` @@ -133,23 +133,22 @@ Let's try to send some CELO on Alfajores. Make sure you are connected to the Alf Make sure you have some Alfajores CELO to send. If you need some, you can get some from [the faucet here](https://celo.org/developers/faucet). ```jsx live -function MetamaskSendCelo(){ - - const TX_PARAMS = { - to: '0x5038ae19CDf0B623e6e8015249ecF58A1165D653', - from: ethereum.selectedAddress, - value: '0x11111111111111', - } - - async function send(){ - let txID = await window.ethereum.request({ - method: 'eth_sendTransaction', - params: [TX_PARAMS] - }); - console.log(txID) - } - - return +function MetamaskSendCelo() { + const TX_PARAMS = { + to: "0x5038ae19CDf0B623e6e8015249ecF58A1165D653", + from: ethereum.selectedAddress, + value: "0x11111111111111", + }; + + async function send() { + let txID = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [TX_PARAMS], + }); + console.log(txID); + } + + return ; } ``` diff --git a/blog/2021-12-31-using-js-keystores.md b/blog/2021-12-31-using-js-keystores.md new file mode 100644 index 0000000000..54207e91c8 --- /dev/null +++ b/blog/2021-12-31-using-js-keystores.md @@ -0,0 +1,160 @@ +--- +title: Using Keystores Library for Local Key Management +description: Introduction to the keystores library and how to use it for local key management. +slug: /developer-guide/start/using-js-keystores +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [keystores] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +# Keystores Library + +Introduction to the keystores library and how to use it for local key management. + + + +## Getting Started + +This is a JavaScript library that provides functions for creating and interacting with encrypted keystores for private key management. To do this, this library wraps the existing [`ethereumjs-wallet` library](https://github.com/ethereumjs/ethereumjs-wallet), which is a standard library for managing keystores according to the [Web3 Secret Storage Definition](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition). As specified, secrets are encrypted using the Scrypt KDF (Key Derivation Function); in this case, the private key is encrypted with a passphrase (that should be kept secret) and can be decrypted later by the same phrase. Note that a keystore generated for the same (private key, passphrase) multiple times will not yield the same output due to how the KDF works. Keystore files generated by a geth node can be decrypted and accessed with this library, and vice versa. + +**Note that keystore files generated by this library do not contain BLS public keys, meaning that these should not be used for validator signer keys used in consensus.** + +The components of the library are roughly as follows: + +- `KeystoreBase` which wraps the functionality of `ethereumjs-wallet` and exposes functions to: + - import PKs (into encrypted keystores) + - decrypt and get a PK from an encrypted keystore + - change the passphrase on a keystore +- `FileKeystore`, `InMemoryKeystore` which specifiy the IO in addition to the above base class +- `KeystoreWalletWrapper`: (not stable; likely to structurally change) a very simple wrapper for a `Keystore` and `LocalWallet`, which allows a user to decrypt a keystore and pass the key to the `LocalWallet` in order to sign transactions. + +## Usage + +:::warning + +For accounts containing significant funds or otherwise requiring a high degree of security, we **do not** recommend this keystore library! This is only for managing keys for low-risk hot wallets and signers. + +For more stringent security requirements, check out the guide to [Choosing a Wallet](/getting-started/wallets). + +::: + +Depending on your use case, you can either interact directly with the `FileKeystore` (purely for creating and interacting with keystore files, importing or accessing private keys) or else use the `KeystoreWalletWrapper` (combines the keystore functionality with convenient access to the `LocalWallet` for signing tranactions). + +### Using the FileKeystore + +#### Create new keystore and import private key + +This snippet will create a `keystore` directory in the `parentDirectory` and create an encrypted file in the `keystore` directory containing the private key. Note that you can only create a new encrypted file for a private key if there is not already an existing file for that private key. If it already exists, you can change the passphrase (see below), but you may not have multiple files for the same private key in the same `keystore` directory. + +```js +import * as readline from "readline"; +import { FileKeystore } from "@celo/keystores"; + +// This is the directory that will contain a "keystore" directory +const parentDirectory = ""; +// This creates a "keystore" directory if one does not already exist in the parentDirectory +const keystore = new FileKeystore(parentDirectory); + +// Prompt to enter private key and passphrase on the command line +let rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); +const privateKey: string = await new Promise((resolve) => + rl.question("Enter private key:", (answer) => { + resolve(answer); + }) +); +const passphrase: string = await new Promise((resolve) => + rl.question("Enter secret passphrase:", (answer) => { + rl.close(); + resolve(answer); + }) +); +// Import private key into the keystore, which is then stored as an encrypted file +// Should create a file with a name like `UTC--` +await keystore.importPrivateKey(privateKey, passphrase); +// Retrieve all addresses contained in the keystore +console.log("Addresses in keystore: ", await keystore.listKeystoreAddresses()); +``` + +#### Accessing an existing keystore file + +```js +// Keystore already exists +const parentDirectory = '' +const keystore = new FileKeystore(parentDirectory) +const address = '' +const oldPassphrase = '' + +// Decrypt file and retrieve private key +await keystore.getPrivateKey(address, oldPassphrase) + +// Change the passphrase encrypting the file +const newPassphrase = '' +await.keystore.changeKeystorePassphrase(address, oldPassphrase, newPassphrase) + +// Decrypt file and retrieve private key using new passphrase +console.log(await keystore.getPrivateKey(address, newPassphrase)) +``` + +#### Remove (delete) a keystore file for a particular address + +```js +const parentDirectory = ""; +const keystore = new FileKeystore(parentDirectory); +const address = ""; + +// When you know the address +// Get the filename (keystore name) +const keystoreName = await keystore.getKeystoreName(address); +await keystore.removeKeystore(keystoreName); + +// Alternatively, you can do this by passing in the filename directly +keystore.removeKeystore(""); +``` + +### Using the KeystoreWalletWrapper + +This example will instantiate a `KeystoreWalletWrapper`, import a private key, and use the inner `LocalWallet` within the wrapper to sign and send a transaction with `ContractKit`. + +```js +import { newKit } from "@celo/contractkit"; +import { FileKeystore, KeystoreWalletWrapper } from "@celo/keystores"; + +// This is the directory that will contain a "keystore" directory +const parentDirectory = + "/celo/celo-monorepo/packages/sdk/wallets/wallet-keystore/test-keystore-dir"; +// Instantiate a KeystoreWalletWrapper using a FileKeystore +const keystoreWalletWrapper = new KeystoreWalletWrapper( + new FileKeystore(parentDirectory) +); +// Make sure to not commit this if using real funds! +// You can also get this as input on the command-line using `readline` +// as in the example above for FileKeystore +const privateKey = "YOUR_TEST_PRIVATE_KEY"; +const passphrase = "test-passphrase1! "; + +// Import private key or unlock account +await keystoreWalletWrapper.importPrivateKey(privateKey, passphrase); +// If the keystore file already exists for an address, simply unlock: +// const address = 'YOUR_TEST_ADDRESS' +// await keystoreWalletWrapper.unlockAccount(address, passphrase) + +// Get the wrapper's `LocalWallet` instance and pass this into ContractKit +const wallet = keystoreWalletWrapper.getLocalWallet(); +const kit = newKit("https://alfajores-forno.celo-testnet.org", wallet); +const [from] = wallet.getAccounts(); + +// Send a test transaction +const gold = await kit.contracts.getGoldToken(); +await gold + .transfer("0x22579ca45ee22e2e16ddf72d955d6cf4c767b0ef", "1") + .sendAndWaitForReceipt({ from }); +console.log("Transaction sent!"); +``` diff --git a/blog/2022-01-01-hellocelo.md b/blog/2022-01-01-hellocelo.md new file mode 100644 index 0000000000..c0fd91cb7d --- /dev/null +++ b/blog/2022-01-01-hellocelo.md @@ -0,0 +1,353 @@ +--- +title: Sending CELO & Stable Assets +description: How to connect to the Celo test network and tranfer tokens using ContractKit. +slug: /developer-guide/start/hellocelo +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [tokens, celo wallet, contractkit, sdk, ledger] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +# Sending CELO & Stable Assets + +How to connect to the Celo test network and tranfer tokens using ContractKit. + + + +## Hello Celo: sending value with Celo + +In this guide we are going to write a Node.js script to introduce some of the basic concepts that are important to understand how Celo works. This will get us started with connecting to the Celo network and learning how to develop more advanced applications. + +:::info + +We assume you already have Node.js and NPM installed on your computer. + +::: + +## Learning Objectives + +At the end of this guide, you will be able to: + +- Connect to the Celo test network, called Alfajores +- Get test CELO, Celo Dollars (cUSD) and Celo Euros (cEUR) from the faucet +- Read account and contract information from the test network +- Transferring CELO, cUSD and cEUR on the test network + +## Getting Started + +To start, [clone this GitHub repo](https://github.com/critesjosh/helloCelo). This is a Node.js application. + +``` +git clone https://github.com/critesjosh/helloCelo.git +``` + +We will be using the Celo ContractKit SDK to interact with the Celo test network (Alfajores). Let's install it. It is already defined in the package.json, so we can get it with + +``` +cd helloCelo +npm install +``` + +## Importing ContractKit + +We will be writing our Node.js app in the `helloCelo.js` file. + +Import the contract kit into our script with + +```javascript title="helloCelo.js" +// 1. Import web3 and contractkit +const Web3 = require("web3"); +const ContractKit = require("@celo/contractkit"); +``` + +Now we can use the ContractKit to connect to the test network. + +```javascript title="helloCelo.js" +// 2. Init a new kit, connected to the alfajores testnet +const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); +const kit = ContractKit.newKitFromWeb3(web3); +``` + +:::info + +At any point in the file you can `console.log()` variables to print their output when you run the script. + +::: + +## Reading Alfajores + +ContractKit contains a `contracts` property that we can use to access certain information about deployed Celo contracts. + +:::info + +The Celo blockchain has two native assets, CELO \(CELO\) and the Celo Dollar \(cUSD\). Both of these assets implement the [ERC20 token standard](https://eips.ethereum.org/EIPS/eip-20) from Ethereum. The CELO asset is managed by the CELO smart contract and Celo Dollars is managed by the cUSD contract. We can access the CELO contract via the SDK with `kit.contracts.getGoldToken()` and the cUSD contract with `kit.contracts.getStableToken()`. These functions return promises, so we have to wait for them to resolve before we can interact with the token contracts. If you are unfamiliar with Promises in Javascript, [check out this documentation.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) Promises are a common tool in blockchain development. In this guide, we use the [async/await syntax for promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await). + +::: + +Let's read some token balances from the blockchain. Add the following line in the `readAccount()` function. + +```javascript title="helloCelo.js" +// 3. Get the token contract wrappers +let celotoken = await kit.contracts.getGoldToken(); +let cUSDtoken = await kit.contracts.getStableToken(); +let cEURtoken = await kit.contracts.getStableToken("cEUR"); +``` + +We can get the CELO balance of an account using the token wrappers like `goldtoken.balanceOf(address)`. Let's check the balance of this address `'0xD86518b29BB52a5DAC5991eACf09481CE4B0710d'`. + +```javascript title="helloCelo.js" +// 4. Address to look up +let anAddress = "0xD86518b29BB52a5DAC5991eACf09481CE4B0710d"; + +// 5. Get token balances +let celoBalance = await celotoken.balanceOf(anAddress); +let cUSDBalance = await cUSDtoken.balanceOf(anAddress); +let cEURBalance = await cEURtoken.balanceOf(anAddress); + +// Print balances +console.log(`${anAddress} CELO balance: ${celoBalance.toString()}`); +console.log(`${anAddress} cUSD balance: ${cUSDBalance.toString()}`); +console.log(`${anAddress} cEUR balance: ${cEURBalance.toString()}`); +``` + +The `balanceOf(address)` function also returns a Promise, so we wait for the promise to resolve then we print the result. + +To view the balances, run the script from the termainal with + +``` +node helloCelo.js +``` + +:::info + +Note that the `balanceOf()` function returns objects with type [BigNumber](https://github.com/MikeMcl/bignumber.js/) because balances are represented in Celo as a 256 bit unsigned integer, and JavaScript's number type cannot safely handle numbers of that size. Note also that the balance values are reported in units of CELO Wei, where one CELO = 10\*\*18 CELO Wei. + +::: + +Reading all account balances is a powerful feature of blockchains. Next, let's see how we can send value to each other on the testnet. + +In order to do transfers (aka [transactions](https://docs.celo.org/getting-started/glossary#transaction)), we need to: + +1. Create an [account](https://docs.celo.org/getting-started/glossary#account) \(by creating a private key\) +2. Fund it with test CELO and cUSDs +3. Sign and send transactions to the network + +## Accounts + +We are accessing the Celo network via a remote [node](https://docs.celo.org/getting-started/glossary#node) via HTTP requests at `'https://alfajores-forno.celo-testnet.org'`. + +:::info + +Don't worry about what this means right now, just understand that it is easier to get started using Celo by accessing remote nodes, rather than running them locally on your machine. You can [read more about the details of the Celo network here.](https://github.com/critesjosh/celo-monorepo/tree/8542c1bc3ad32bc48eed33073f4d34a36fd91fae/packages/docs/celo-sdk/walkthroughs/overview.md#topology-of-a-celo-network) + +::: + +Because we are accessing the network remotely, we need to generate an account to sign transactions and fund that account with test CELO. + +There is a short script in `getAccount.js` to either get a Celo account from a mnemonic in the `.secret` file, or create a random account if the file is empty. In the script, we use`web3.js` to create a new private key/account pair. [Web3.js](https://web3js.readthedocs.io/) is a popular javascript library for handling Ethereum related functionality. Celo is a cousin of Ethereum, so this library works well for generating Celo accounts. + +:::danger + +This is not the standard way of managing Celo accounts. In a production environment, the [Celo Wallet](/celo-codebase/wallet) will manage accounts for you. Accessing accounts from the Celo Wallet will be discussed in future guides. + +::: + +We can now use this `account` to get account information \(ie the private key and account address\) and to send transactions from `account.address`. Add the following code to read the account balance. Continue adding to `helloCelo.js`. + +```javascript title="helloCelo.js" +// +// Create an Account +// + +// 6. Import the getAccount function +const getAccount = require("./getAccount").getAccount; + +async function getBalances() { + // 7. Get your account + let account = await getAccount(); + + // 8. Get the token contract wrappers + let celotoken = await kit.contracts.getGoldToken(); + let cUSDtoken = await kit.contracts.getStableToken(); + let cEURtoken = await kit.contracts.getStableToken("cEUR"); + + // 9. Get your token balances + let celoBalance = await celotoken.balanceOf(account.address); + let cUSDBalance = await cUSDtoken.balanceOf(account.address); + let cEURBalance = await cEURtoken.balanceOf(account.address); + + // Print your account info + console.log(`Your account address: ${account.address}`); + console.log(`Your account CELO balance: ${celoBalance.toString()}`); + console.log(`Your account cUSD balance: ${cUSDBalance.toString()}`); + console.log(`Your account cEUR balance: ${cEURBalance.toString()}`); +} +``` + +Run this script again with `node helloCelo.js`. This will print `0`, as we have not funded the associated account yet. + +## Using the faucet + +We can get free test CELO and cUSDs on the test network for development via [the Celo Alfajores faucet](https://celo.org/build/faucet). + +Copy your randomly generated account address from the console output mentioned above, and paste it into the faucet. + +Once your account has been funded, run `$ node helloCelo.js` again to see your updated balance. + +## Sending Value + +We have an account with CELO and cUSD in it, now how do we send tokens to another account? Remember the token wrappers we used to read account balances earlier? We can use the same wrappers to send tokens, you just need to add the private key associated with your account to ContractKit \(see line 10\). + +The token wrappers have a method called `transfer(address, amount)` that allows you to send value to the specified address \(line 14\). + +You need to `send()` the transaction to the network after you construct it. The `send()` methods accepts an option that allows you to specify the `feeCurrency`, which allows the sender to pay transaction fees in CELO or cUSD. The default `feeCurrency` is CELO. In the following example, let's pay transaction fees in CELO when we transfer CELO and pay with cUSD when we transfer cUSD. + +The `send()` method returns a transaction object. We will wait for the transaction receipt \(which will be returned when the transaction has been included in the blockchain\) and print it when we get it. This receipt contains information about the transaction. + +After we read the receipt, we check the balance of our account again, using the `balanceOf()` function. The logs print our updated balance! + +You may notice that the account balance is a bit smaller than the amount of tokens that we sent. This is because you have to pay for every update to the network. + +Add the following code to the `send()` function in `helloCelo.js` to send a transaction. + +```javascript title="helloCelo.js" +async function send() { + // 10. Get your account + let account = await getAccount(); + + // 11. Add your account to ContractKit to sign transactions + kit.connection.addAccount(account.privateKey); + + // 12. Specify recipient Address + let anAddress = "0xD86518b29BB52a5DAC5991eACf09481CE4B0710d"; + + // 13. Specify an amount to send + let amount = 100000; + + // 14. Get the token contract wrappers + let celotoken = await kit.contracts.getGoldToken(); + let cUSDtoken = await kit.contracts.getStableToken(); + let cEURtoken = await kit.contracts.getStableToken("cEUR"); + + // 15. Transfer CELO and cUSD from your account to anAddress + // Optional: specify the feeCurrency, default feeCurrency is CELO + let celotx = await celotoken + .transfer(anAddress, amount) + .send({ from: account.address }); + let cUSDtx = await cUSDtoken + .transfer(anAddress, amount) + .send({ from: account.address, feeCurrency: cUSDtoken.address }); + let cEURtx = await cEURtoken + .transfer(anAddress, amount) + .send({ from: account.address }); + + // 16. Wait for the transactions to be processed + let celoReceipt = await celotx.waitReceipt(); + let cUSDReceipt = await cUSDtx.waitReceipt(); + let cEURReceipt = await cEURtx.waitReceipt(); + + // 17. Print receipts + console.log("CELO Transaction receipt: %o", celoReceipt); + console.log("cUSD Transaction receipt: %o", cUSDReceipt); + console.log("cEUR Transaction receipt: %o", cEURReceipt); + + // 18. Get your new balances + let celoBalance = await celotoken.balanceOf(account.address); + let cUSDBalance = await cUSDtoken.balanceOf(account.address); + let cEURBalance = await cEURtoken.balanceOf(account.address); + + // 19. Print new balance + console.log(`Your new account CELO balance: ${celoBalance.toString()}`); + console.log(`Your new account cUSD balance: ${cUSDBalance.toString()}`); + console.log(`Your new account cUSD balance: ${cEURBalance.toString()}`); +} +``` + +Run `$ node helloCelo.js` again to send the transactions and see the printed output in the console. + +## Connecting to a Ledger Device from a Web Application + +The above instructions apply to building NodeJS applications. If you want to build an integration with a web application, you can still use the ContractKit by following slightly modified instructions. + +The following code examples are typescript so should be stored in a `.tsc` file, you will also need to install typescript and then compile your typescript to javascript with `npx tsc` before you can run the code with node. + +``` +npm install --save-dev typescript +npm install web3 @celo/contractkit @celo/wallet-ledger @ledgerhq/hw-app-eth @ledgerhq/hw-transport-u2f @ledgerhq/hw-transport-webusb +``` + +Then, you can create a new instance of the ContractKit with the following code: + +```javascript +import { ContractKit, newKitFromWeb3 } from "@celo/contractkit"; +import { newLedgerWalletWithSetup } from "@celo/wallet-ledger"; +import Eth from "@ledgerhq/hw-app-eth"; +import TransportU2F from "@ledgerhq/hw-transport-u2f"; +import TransportUSB from "@ledgerhq/hw-transport-webusb"; +import Web3 from "web3"; + +// Handle getting the Celo Ledger transport. +const getCeloLedgerTransport = () => { + if (window.USB) { + return TransportUSB.create(); + } else if (window.u2f) { + return TransportU2F.create(); + } + + throw new Error( + "Ledger Transport not support, please use Chrome, Firefox, Brave, Opera or Edge." + ); +}; + +// Handle creating a new Celo ContractKit +const getContractKit = async () => { + // Create a Web3 provider by passing in the testnet/mainnet URL + const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); + + // Get the appropriate Ledger Transport + const transport = await getCeloLedgerTransport(); + + // Create a new instance of the ETH Ledger Wallet library + const eth = new Eth(transport); + + // Use the Celo Ledger Wallet setup util + const wallet = await newLedgerWalletWithSetup(eth.transport); + + // Instantiate the ContractKit + const kit: ContractKit = newKitFromWeb3(web3, wallet); + + return kit; +}; +``` + +Once you have successfully created the ContractKit, you can use the various Celo contracts to sign transactions with a connected Ledger device. For example, here's how to transfer gold tokens (just like above in the NodeJS example): + +```javascript +// Use the gold token contract to transfer tokens +const transfer = async (from, to, amount) => { + const celoTokenContract = await kit.contracts.getGoldToken(); + const tx = await celoTokenContract.transfer(to, amount).send({ from }); + const receipt = await tx.waitReceipt(); + console.log("Transaction Receipt: ", receipt); +}; +``` + +This is the basic setup to integrate the Celo Ledger App with a web application. You can also view the [Celo Ledger App example codebase](https://github.com/celo-org/celo-ledger-web-app) for some other examples of connecting to a Ledger Device from a web application. + +## Wrapping Up + +Congratulations! You have accomplished a lot in this short introduction to developing on Celo. + +We covered: + +- Installing and setting up ContractKit +- Connecting to the Celo Alfajores network +- Getting the CELO contract wrapper +- Reading account balances using the CELO wrapper +- Generating a new account in Celo +- Funding an account using the Celo Alfajores Faucet +- Sending CELO diff --git a/blog/2022-01-02-hellocontracts.md b/blog/2022-01-02-hellocontracts.md new file mode 100644 index 0000000000..ec956d56a0 --- /dev/null +++ b/blog/2022-01-02-hellocontracts.md @@ -0,0 +1,219 @@ +--- +title: "Deploy a Contract on Celo (local node)" +description: How to deploy your own smart contracts onto Celo from a local node. +slug: /developer-guide/start/hellocontracts +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [smart contract] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +# Deploy a Contract (Local Node) + +How to deploy your own smart contracts onto a Celo local node. + + + +:::tip + +As Celo is fully EVM compliant, we inherit the rich developer ecosystem and tooling of the Ethereum community. We will be deploying a typical hello world smart contract onto the Alfajores testnet with typical Ethereum tools like Truffle and Ganache. + +::: + +## Setup + +This guide assumes that you have a basic Node/[NPM](https://www.npmjs.com/get-npm) setup (Node.js v12.x). If so, you can install truffle with: + +``` +npm install -g truffle +``` + +In your desired project folder, intiialize a new truffle project: + +``` +truffle init +``` + +## Hello World! + +Let's add a contract with + +``` +truffle create contract HelloWorld +``` + +Our contract will just store a name for now: + +```solidity +pragma solidity >=0.5.0 <0.7.0; + +contract HelloWorld { + string name = 'Celo'; + + function getName() public view returns (string memory) { + return name; + } + + function setName(string calldata newName) external { + name = newName; + } +} +``` + +## Deploy locally + +Let's create a migration to deploy the contract. For that, we need to create a file in the `migrations` folder named `2_deploy_helloworld.js`: + +```javascript +var HelloWorld = artifacts.require("HelloWorld"); + +module.exports = function (deployer) { + deployer.deploy(HelloWorld); +}; +``` + +To be able to actually deploy it though, we need a blockchain. For local development and testing, you can use our fork of ganache: + +``` +npm install -g @celo/ganache-cli +``` + +And then start ganache with: + +``` +ganache-cli --port 7545 +``` + +In your `truffle-config.js`, you'll want to add your local test network under networks: + +``` + networks: { + test: { + host: "127.0.0.1", + port: 7545, + network_id: "*" + } + } +``` + +Then you can deploy your contract to your local network first: + +``` +truffle migrate --network test +``` + +You can interact with your contract by running the truffle console: + +``` +truffle console --network test +truffle(test)> contract = await HelloWorld.deployed() +undefined +truffle(test)> contract.getName() +'Celo' +truffle(test)> contract.setName('MyName') +{ tx: +... +truffle(test)> contract.getName() +'MyName' +``` + +## Deploy to Alfajores + +When you are ready to deploy your contract to Alfajores, you'll need a Celo client connected to the testnet. We'll run a node somewhat similarly to the [Instructions of running a full node on Baklava](/getting-started/baklava-testnet/running-a-full-node-in-baklava): + +```bash +export CELO_IMAGE=us.gcr.io/celo-org/geth:alfajores +``` + +### Pull the Celo Docker image + +We're going to use a Docker image containing the Celo node software in this tutorial. + +If you are re-running these instructions, the Celo Docker image may have been updated, and it's important to get the latest version. + +```bash +docker pull $CELO_IMAGE +``` + +### Set up a data directory + +First, create the directory that will store your node's configuration and its copy of the blockchain. This directory can be named anything you'd like, but here's a default you can use. The commands below create a directory and then navigate into it. The rest of the steps assume you are running the commands from inside this directory. + +```bash +mkdir celo-data-dir +cd celo-data-dir +``` + +### Create an account and get its address + +In this step, you'll create an account on the network. If you've already done this and have an account address, you can skip this and move on to configuring your node. + +Run the command to create a new account: + +```bash +docker run -v $PWD:/root/.celo --rm -it $CELO_IMAGE account new +``` + +It will prompt you for a passphrase, ask you to confirm it, and then will output your account address: `Address: {` + +Save this address to an environment variables, so that you can reference it below (don't include the braces): + +```bash +export CELO_ACCOUNT_ADDRESS= +``` + +_Note: this environment variable will only persist while you have this terminal window open. If you want this environment variable to be available in the future, you can add it to your `~/.bash_profile_ + +### Start the node + +This command specifies the settings needed to run the node, and gets it started. + +```bash +docker run --name celo-ultralight-node -d --restart unless-stopped -p 127.0.0.1:8545:8545 -v $PWD:/root/.celo $CELO_IMAGE --verbosity 3 --syncmode lightest --rpc --rpcaddr 0.0.0.0 --rpcapi eth,net,web3,debug,admin,personal --etherbase $CELO_ACCOUNT_ADDRESS --alfajores --datadir=/root/.celo --allow-insecure-unlock +``` + +You can follow the logs with + +```bash +docker logs -f celo-ultralight-node +``` + +After a few seconds of syncing (with [Celo's ultralight sync](/celo-codebase/protocol/consensus/ultralight-sync)), you should be able to query the balance of your account: + +```bash +docker exec celo-ultralight-node geth attach --exec 'eth.getBalance("")' +``` + +If you go to our [Alfajores Faucet Page](https://celo.org/build/faucet), you should be able to faucet your account some CELO and see your balance increase with the above command. + +### Deploy the contract + +We are finally ready to deploy the contract. First let's unlock the account: + +```bash +docker exec celo-ultralight-node geth attach --exec 'personal.unlockAccount("", "")' +``` + +In your `truffle-config.js` reference your node: + +``` +alfajores: { + host: "127.0.0.1", + port: 8545, + network_id: 44787 +} +``` + +Then you should be able to deploy your contract with: + +``` +truffle migrate --network alfajores +``` + +You can verify your contract deployment on [Blockscout](https://alfajores-blockscout.celo-testnet.org/), as well as interact with your new contract with the `truffle console --network alfajores`. Congratulations! + +As you can see, all the goodies from Ethereum apply to Celo, so virtually all tutorials and other content should be easily translatable to Celo. Check out [https://celo.org/build](https://celo.org/build) for more resources! diff --git a/blog/2022-01-03-hello-contract-remote-node.md b/blog/2022-01-03-hello-contract-remote-node.md new file mode 100644 index 0000000000..ffeccdbf5d --- /dev/null +++ b/blog/2022-01-03-hello-contract-remote-node.md @@ -0,0 +1,329 @@ +--- +title: Deploy and Interact with Contracts (Remotely) +description: How to deploy and interact your own smart contracts using a remote node. +slug: /developer-guide/start/hello-contract-remote-node +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [smart contract, remote, deploy] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +import PageRef from '@components/PageRef' + +# Hello Contract \(Truffle + Remote Node\) + +How to deploy and interact your own smart contracts using a remote node. + + + +:::tip + +As Celo is fully EVM compatible, we inherit the rich developer ecosystem and tooling of the Ethereum community. You will be deploying a typical hello world smart contract onto the Alfajores testnet with the common Ethereum tool, Truffle. + +::: + +:::note + +This page is similar to the Hello Contracts page, but this one will connect to a remote node (Forno) and do key management in the Truffle project. + +::: + +## Setup + +This guide assumes that you have a basic Node/[NPM](https://www.npmjs.com/get-npm) setup. + +:::info + +[Learn more about the Truffle development framework here.](https://www.trufflesuite.com/docs/truffle/overview) + +::: + +As you may know, Truffle is built for Ethereum developers. Because Celo has a similar network architecture and runs the Ethereum Virtual Machine, Celo developers are able to leverage many Ethereum developer tools. But it is important to keep in mind the differences. If you haven't already, please review the Celo overview. + + + +[Clone this Truffle project from GitHub to get started](https://github.com/critesjosh/hello_contract-truffle). + +``` +git clone https://github.com/critesjosh/hello_contract-truffle.git +``` + +This is a basic truffle project, with some additional files to help us with account management and deploying to a remote Celo test net node. Run `npm install` to install of the project dependencies. + +## Hello World! + +Add a contract with the command + +```text +truffle create contract HelloWorld +``` + +We will not go into the details of how to write Solidity in this exercise, but you can learn more at the [Solidity documentation page](https://solidity.readthedocs.io/en/latest/). + +The contract will just store a name for now: + +```solidity title="contracts/HelloWorld.sol" + +pragma solidity >=0.5.0 <0.8.0; + +contract HelloWorld { + string name = 'Celo'; + + function getName() public view returns (string memory) { + return name; + } + + function setName(string calldata newName) external { + name = newName; + } +} +``` + +## Prepare Deployment + +### Compile the contract + +Before you deploy the contract, you need to compile the Solidity code into Ethereum bytecode. The following truffle command will look in the `./contracts` directory and compile any new or updated Solidity (`.sol`) contracts. + +``` +truffle compile +``` + +After compiling the contract, you need to create a migration to deploy the contract. For that, create a file in the `./migrations/` folder named `2_deploy_helloworld.js`: + +:::info + +[Learn more about Truffle migrations here.](https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations) + +::: + +```javascript title="migrations/2_deploy_helloworld.js" +var HelloWorld = artifacts.require("HelloWorld"); + +module.exports = function (deployer) { + deployer.deploy(HelloWorld); +}; +``` + +:::info + +You can [learn more about Truffle configuration options here.](https://www.trufflesuite.com/docs/truffle/reference/configuration) + +::: + +## Deploy to Alfajores \(Remotely\) + +When you deploy contracts to the Celo network with a remote node, you have to sign the contract deployment transaction locally before sending it to the remote node to be broadcast to the network. This presents some unique challenges when using Ethereum development tools \(like Truffle\) because Celo transaction objects are slightly different than Ethereum transaction objects. + +When you are ready to deploy your contract to Alfajores, you'll need a Celo client connected to the testnet. In this exercise you will connect to a remote node to read and write to the public testnet (Alfajores), but you could also run a testnet node locally to perform the same actions. + +Here are the steps to go through to deploy the contract to the Alfajores testnet. + +1. Connect to Forno \(a remote Celo node service provider\) +2. Get personal account information \(generate a private key if required, stored in `./.env`\) +3. Get your personal account address and fund it via the [faucet](https://celo.org/build/faucet) +4. Get the compiled contract bytecode +5. Create and sign the contract deployment transaction +6. Send transaction to the network + +Make sure the dependencies are installed with: + +```text +yarn install +``` + +Run the createAccount.js script with: + +```text +node createAccount.js +``` + +```javascript title="createAccount.js" +const Web3 = require("web3"); +const web3 = new Web3("http://localhost:8545"); + +console.log(web3.eth.accounts.create()); +``` + +The provided code will print a private key / account pair in the terminal. Copy and paste the printed `priavteKey` into a `PRIVATE_KEY` variable in a file called `.env`, similar to what is shown in the `.envexample` file. The `address` that is printed with the private key is the account that we will fund with the faucet. + +If you go to the [Alfajores Faucet Page](https://celo.org/build/faucet), you can faucet your account some CELO and see your balance increase. + +### Deploy the contract + +#### Truffle Deployment + +Before you can use truffle for the migration, you need to set up the proper configuration in `./truffle-config.js`. At the top of `./truffle-config.js`, set up the `kit` by connecting to the test network and adding the account you just funded. + +```javascript title="truffle.config.js" +const ContractKit = require("@celo/contractkit"); +const Web3 = require("web3"); +require("dotenv").config(); + +const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); +const kit = ContractKit.newKitFromWeb3(web3); + +kit.connection.addAccount(process.env.PRIVATE_KEY); +``` + +Then, in the `networks` object, you can add the initialized `kit`provider to an `alfajores` property. + +```javascript title="truffle.config.js" + networks: { + test: { + host: "127.0.0.1", + port: 7545, + network_id: "*" + }, + alfajores: { + provider: kit.connection.web3.currentProvider, // CeloProvider + network_id: 44787, // Alfajores network id + gas: 4000000, // You need to include the gas limit + } + } +``` + +:::info + +Truffle doesn't estimate the gas properly, so you need to specify a gas limit in `truffle.config.js`. + +::: + +Now, deploy the contracts to Alfajores with this command: + +```javascript +truffle migrate --network alfajores +``` + +#### Custom Node.js Deployment + +In this section, you will deploy a contract using a simple Node.js script to show how you can do it without using Truffle. + +You need to compile the `HelloWorld.sol` contract using \(if it isn't already\): + +```javascript +truffle compile +``` + +This command will generate a `HelloWorld.json` file in the `./build/contracts/` directory. `HelloWorld.json` contains a lot of data about the contract, compiler and low level details. Import this file into the deployment script `celo_deploy.js` with: + +```javascript +const HelloWorld = require("./build/contracts/HelloWorld.json"); +``` + +You are finally ready to deploy the contract. Use the `kit`to create a custom transaction that includes the contract bytecode. + +```javascript title="celo_deploy.js" +let tx = await kit.connection.sendTransaction({ + from: address, + data: HelloWorld.bytecode, // from ./build/contracts/HelloWorld.json +}); +``` + +:::info + +To deploy a contract on Celo, use the `kit.connection.sendTransaction()` function with no `to:` field and the contract bytecode in the `data` field. The account that you are sending the transaction from must have enough CELO to pay the transaction fee, unless you specify another currency as the `feeCurrency`, then you need enough of that currency to pay the transaction fee. + +::: + +The entire deployment script is about 20 lines of code. + +```javascript title="celo_deploy.js" +const Web3 = require("web3"); +const ContractKit = require("@celo/contractkit"); +const web3 = new Web3("https://alfajores-forno.celo-testnet.org"); +const privateKeyToAddress = + require("@celo/utils/lib/address").privateKeyToAddress; +const kit = ContractKit.newKitFromWeb3(web3); +require("dotenv").config(); +const HelloWorld = require("./build/contracts/HelloWorld.json"); + +async function awaitWrapper() { + kit.connection.addAccount(process.env.PRIVATE_KEY); // this account must have a CELO balance to pay transaction fees + + // This account must have a CELO balance to pay tx fees + // get some testnet funds at https://celo.org/build/faucet + const address = privateKeyToAddress(process.env.PRIVATE_KEY); + console.log(address); + + let tx = await kit.connection.sendTransaction({ + from: address, + data: HelloWorld.bytecode, + }); + + const receipt = await tx.waitReceipt(); + console.log(receipt); +} + +awaitWrapper(); +``` + +Congratulations! You have deployed your first contract onto Celo! You can verify your contract deployment on [Blockscout](https://alfajores-blockscout.celo-testnet.org/). You can get the transaction hash from the receipt and look it up on the block explorer. + +### Interacting with Custom Contracts + +Now HelloWorld.sol is deployed onto the Alfajores testnet. How can you interact with the deployed contract using ContractKit? `helloWorld.js` includes some example code that shows how you can do this. + +There are 3 functions defined in `helloWorld.js` that accomplish this. + +The first function, `initContract()`, reads the deployed contract information from the Truffle artifact at `HelloWorld.json`. With this information, you can create a new web3.js Contract instance: + +```javascript title="helloWorld.js" +async function initContract() { + // Check the Celo network ID + const networkId = await web3.eth.net.getId(); + + // Get the contract associated with the current network + const deployedNetwork = HelloWorld.networks[networkId]; + + // Create a new contract instance with the HelloWorld contract info + let instance = new kit.web3.eth.Contract( + HelloWorld.abi, + deployedNetwork && deployedNetwork.address + ); + + getName(instance); + setName(instance, "hello world!"); +} +``` + +After creating the contract instance, the `initContract()` function calls `getName()` and `setName()`. + +The `getName()` function will call, return and print the `getName()` function of the provided instance of the HelloWorld contract. + +```javascript title="helloWorld.js" +async function getName(instance) { + let name = await instance.methods.getName().call(); + console.log(name); +} +``` + +The `setName()` function is a bit more involved. First, it gets the account key from the provided `./secret` file, just like in `celo_deploy.js`. Then it creates a `txObject` that encodes a smart contract transaction call to `setName()` with the provided `newName` to the provided instance of the HelloWorld contract. Then the function sends the encoded transaction object to the network, waits for a reciept and prints it to the console. + +```javascript title="helloWorld.js" +async function setName(instance, newName) { + // Add your account to ContractKit to sign transactions + // This account must have a CELO balance to pay tx fees, get some https://celo.org/build/faucet + kit.connection.addAccount(process.env.PRIVATE_KEY); + const address = privateKeyToAddress(process.env.PRIVATE_KEY); + + // Encode the transaction to HelloWorld.sol according to the ABI + let txObject = await instance.methods.setName(newName); + + // Send the transaction + let tx = await kit.sendTransactionObject(txObject, { from: address }); + + let receipt = await tx.waitReceipt(); + console.log(receipt); +} +``` + +The above method shows a more detail about how to create custom deployment transactions and scripts than the previous method. + +As you can see, all the goodies from Ethereum apply to Celo, so virtually all tutorials and other content should be easily translatable to Celo. + +Check out [https://celo.org/build](https://celo.org/build) for more resources! diff --git a/blog/2022-01-04-no-code-erc20.md b/blog/2022-01-04-no-code-erc20.md new file mode 100644 index 0000000000..eb9aefd3f6 --- /dev/null +++ b/blog/2022-01-04-no-code-erc20.md @@ -0,0 +1,83 @@ +--- +title: Deploy & Mint a Token +description: How to deploy an ERC20 token contract to Celo. +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [tokens, ERC20, mint, solidity, open zeppelin, remix] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +# Deploy an ERC20 token to Celo + +How to deploy a token contract that use the ERC20 token standard to Celo without writing code. + + + +## Getting Started + +In this tutorial, we will go over how to deploy an ERC20 token contract. The process is very similar for deploying other tokens as well. + +1. Install [Metamask](https://metamask.io/). +2. [Add the Celo network](/getting-started/wallets/using-metamask-with-celo/manual-setup#adding-a-celo-network-to-metamask) to Metamask. We suggest adding the Alfajores testnet to Metamask as well, so you can test contract deployments before deploying to mainnet. +3. Add a small amount of CELO to your Metamask account. In this example, we will deploy to the Alfajores testnet, so we need Alfajores CELO, which you can get from the faucet [here](https://celo.org/developers/faucet). +4. Go to the [Open Zeppelin Contracts Wizard](https://docs.openzeppelin.com/contracts/4.x/wizard). +5. Select `ERC20` as the type of contract that you would like to deploy. + +![erc20 empty settings.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/erc20%20empty%20settings.png?raw=true) + +6. Name your token. We are calling our token “ProsperityToken” in this example. +7. Select the features for your token. We are making ProsperityToken mintable, burnable and enabling snapshots, so the token may be used for governance. We are also making the contract Ownable, so the deployer of the contract can mint new tokens and distribute them as desired. Ideally, the owner account will be a multi-signature contract, so no single person has control over this token contract. + If you want the block explorer to recognize your token then leave "Upgradeability" unchecked and do not select one of the two radio options below it. Selecting one of these options will prevent the [Celo block explorer](https://explorer.celo.org/) from recognizing your deployed contract as a token. If you want upgradability and do not care about the block explorer, feel free to make your token contract upgradable. + +![erc20 filled settings.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/erc20%20filled%20settings.png?raw=true) + +8. Open your contract in Remix by clicking “Open in Remix”. Remix will pop open with the contract code already filled in. +9. Click the big blue button that says “Compile contract-xxxxx.sol”. The contract should compile without error. + +![remix compile erc20.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/remix%20compile%20erc20.png?raw=true) + +10. Click the Ethereum logo in the left sidebar. This will bring up a new interface for deploying the contract. + +![remix deploy erc20.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/remix%20deploy%20erc20.png?raw=true) + +11. In the “Environment” section on the top left, select “Injected Web3”. This will connect Remix to Metamask. Now clicking the “deploy” button will deploy the contracts to whichever network Metamask is connected to. You should see a small textbox indicating that Remix is connected to a custom network. The Alfajores network id is 44787. + +![select injected web3.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/select%20injected%20web3.png?raw=true) + +12. In the Contract dropdown, select the contract that you want to deploy. In this example, it is called ProsperityToken. + +![select prosperitytoken erc20 contract.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/select%20prosperitytoken%20erc20%20contract.png?raw=true) + +13. Click Deploy. Metamask should pop open. + +![deploy prosperity token erc20.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/deploy%20prosperity%20token%20erc20.png?raw=true) + +14. Click Confirm. Once the transaction confirms (less than 5 seconds), a contract interface will appear in the bottom left, and transaction details will appear in the console at the bottom. + +![deployed prosperity token.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/deployed%20prosperity%20token.png?raw=true) + +That’s it! We now have ProsperityToken deployed on Alfajores with the Metamask account as the contract owner. + +You can see the contract information on the [Alfajores block explorer](https://alfajores-blockscout.celo-testnet.org/). Copy and paste the contract address or deployment transaction hash from the console output and paste it into the block explorer search bar or look up the deployment transaction info in the Metamask activity. + +## Deploying your token on the Mainnet + +When you're ready to deploy your token to the Celo Mainnet make sure to change the network of your connected wallet from Alfajores to the Celo Mainnet. Once you have done this you can simply redeploy the contract (you will not need to recompile it). + +Note: When deploying to the Mainnet you will need to use real Celo to pay the gas fee (as opposed to using the faucet on the testnet). As of December 2021 this cost is less than $0.01 US. You can learn how to [get Celo here](https://celo.org/buy). + +You can read about how to add your new token to the Celo Wallet [here](/blog/add-token-celo-wallet). + +## Verify + +If you are unable to view your token on the block explorer, you may need to Verify it first. If you are able to see your token, you may skip this section. + +Verifying your contract with Remix is straight-forward and allows anyone to read and interact with the contract on the block explorer. You can read more about verifying a contract with Remix on [this page](/developer-resources/deploy-remix#verify-the-smart-contract). + +You can find my example contract [here](https://alfajores-blockscout.celo-testnet.org/address/0x97d550A2540F902F4501e21A6c09f12B69173261/transactions). + +Let me know what you end up building and reach out if you have any questions, [@critesjosh\_](https://twitter.com/critesjosh_) on Twitter or joshc#0001 on Discord. Join the Celo discord at https://chat.celo.org. diff --git a/blog/2022-01-05-no-code-erc721.md b/blog/2022-01-05-no-code-erc721.md new file mode 100644 index 0000000000..da105c4be1 --- /dev/null +++ b/blog/2022-01-05-no-code-erc721.md @@ -0,0 +1,64 @@ +--- +title: "Deploy an NFT to Celo" +description: How to deploy ERC721 tokens (NFTs) on the Celo network using autogenerated code. +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [tokens, ERC721, mint, NFT, ipfs, pinata, solidity, remix] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +# Deploy an NFT to Celo + +How to deploy ERC721 tokens (NFTs) on the Celo network using autogenerated code. + + + +## Getting Started + +In this example, we will be using IPFS for off-chain storage, but you can use whatever off-chain storage mechanism you want. + +## Set up your wallet + +1. Install [Metamask](https://metamask.io/). +2. [Add the Celo network](/getting-started/wallets/using-metamask-with-celo/manual-setup#adding-a-celo-network-to-metamask) to Metamask. We suggest adding the Alfajores testnet to Metamask as well, so you can test contract deployments before deploying to mainnet. +3. Add a small amount of CELO to your Metamask account. In this example, we will deploy to the Alfajores testnet, so we need Alfajores CELO, which you can get from the faucet [here](https://celo.org/developers/faucet). + +## Prepare the NFT metadata + +4. Go to [https://app.pinata.cloud/](https://app.pinata.cloud/) and sign up for an account if you don’t have one already. Pinata is a service that allows you to easily upload files to [IPFS](https://ipfs.io/). +5. Upload your NFT images to IPFS. Because storing data on a blockchain can be expensive, NFTs often reference off-chain data. In this example, We are creating a set of NFTs that reference pictures of trees. We uploaded all of the images of trees to IPFS individually. The names of the images correspond to the token ID. This isn’t necessary, we just did it for convenience. Notice that each image has a corresponding CID hash, this is the unique identifier for that file or folder. ![pinata upload image list.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/pinata%20upload%20image%20list.png?raw=true) +6. Once all of your images have been uploaded, you will need to prepare the token metadata in a new folder. + 1. We created a folder called “prosper factory metadata”. You can view the contents of the folder [here](https://gateway.pinata.cloud/ipfs/QmdmA3gwGukA8QDPH7Ypq1WAoVfX82nx7SaXFvh1T7UmvZ). The folder contains 14 files, numbered 0-13. **The names of these files are important.** These file names correspond to the token ID of each NFT that will be created by the contract. Make sure that there are no extensions (.txt, .json, .jpeg, .png) on your files. ![ipfs folder contents.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/ipfs%20folder%20contents.png?raw=true) + 2. Click on one of the files. The files contain the NFT metadata. In this simple example, the metadata only contains a reference to the unique tree image. You can view the image in a browser that supports IPFS (we are using Brave) here. Each file should have a unique image reference. ![ipfs image metadata.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/ipfs%20image%20metadata.png?raw=true) You will need to create a similarly structured folder containing metadata for all of the NFTs that you want to create. +7. Upload the folder containing all of the token metadata to IPFS. This will make your NFT data publicly available. We called ours “prosper factory metadata”. Note the CID of this folder. We will need it shortly. ![pinata prosper factory metadata folder.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/pinata%20prosper%20factory%20metadata%20folder.png?raw=true) + +## Design and Deploy the Smart Contracts + +8. Go to [https://docs.openzeppelin.com/contracts/4.x/wizard](https://docs.openzeppelin.com/contracts/4.x/wizard) +9. Select ERC721 as your token choice. +10. Enter your token information. + 1. We are calling our token the ProsperityFactory, symbol PF. + 2. We entered the IPFS CID of our token metadata folder (prosper factory metadata) in the “Base URI” field. Be sure to add a trailing “/” to the base URI, the token ID will be appended to the end of the base URI to get the IPFS metadata file. So the complete Base URI for our NFT contract is `ipfs://QmdmA3gwGukA8QDPH7Ypq1WAoVfX82nx7SaXFvh1T7UmvZ/`. Again, you can view the folder [here](https://gateway.pinata.cloud/ipfs/QmdmA3gwGukA8QDPH7Ypq1WAoVfX82nx7SaXFvh1T7UmvZ). + 3. We made the token mintable and it will automatically increment the token IDs as the tokens are minted. The counter starts at 0 and adds 1 to each successive token. It is important that the file contents of the IPFS metadata folder are labeled accordingly (ie. 0-13) and correspond to the token IDs. + 4. The contract is also marked Ownable, meaning that only the owner of the contract (which is initially set to the account that deploys the contract) can mint new NFTs. ![erc721 filled settings.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/erc721%20filled%20settings.png?raw=true) +11. Click “Open in Remix”. Remix will pop open with your contract code already filled in. +12. Click the big blue button on the left side of Remix that says “Compile contract-xxxx.sol”. ![remix compile erc721.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/remix%20compile%20erc721.png?raw=true) +13. Once the contract is compiled, click the Ethereum logo on the left side of the window. A new sidebar will appear. ![remix deploy page erc721.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/remix%20deploy%20page%20erc721.png?raw=true) +14. In the “Environment” dropdown, select “Injected Web3”. This will connect Remix and Metamask. Make sure that Metamask is connected to the correct network. In this example, We are deploying to the Alfajores testnet, so we see a textbox below the dropdown that says `Custom (44787) network`. 44787 is the network id for Alfajores. ![select injected web3.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/select%20injected%20web3.png?raw=true) +15. Select the contract that you want to deploy. We titled the contract the ProsperityFactory. ![select erc721 contract.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/select%20erc721%20contract.png?raw=true) +16. Click Deploy. Metamask will pop up asking you to confirm the transaction. ![remix deploy 721 tx.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/remix%20deploy%20721%20tx.png?raw=true) +17. Once the contract is deployed, Remix will show a newly deployed contract on the bottom left corner of the window. Expand the ProsperityFactory dropdown to see all of the contract functions. You can see the deployed ProsperityFactory NFT contract [here](https://alfajores-blockscout.celo-testnet.org/address/0xD8ea7beC4820dbC22aCf87EB0cCFE50203a45A6F/transactions). ![remix 721 contract interface.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/remix%20721%20contract%20interface.png?raw=true) +18. Let’s mint the first NFT. To do that we will call the safeMint function. The safeMint function needs an account address as an input, so it knows who to mint the token to. I’ll just enter the first Metamask address and click the orange button. Metamask will pop up, confirm the transaction. When the transaction is confirmed, this will have minted the first NFT, with token ID 0. ![safeMint.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/safeMint.png?raw=true) +19. Check the token metadata. You can verify that the token was minted by calling the “tokenURI” function with the expected token ID. We call the contract with token ID 0 and it returns an IPFS reference. ![721 read token uri.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/721%20read%20token%20uri.png?raw=true) +20. Navigating to this IPFS reference will show the token metadata for that NFT. ![ipfs token metadata.png](https://github.com/critesjosh/images/blob/main/token_deploy_tutorials/ipfs%20token%20metadata.png?raw=true) +21. Going to that IPFS reference will show the image for the token. + +We went through the same process and minted all 14 NFTs from this contract. + +That’s it! You now know how to create your own NFT contract with corresponding metadata! + +Let me know what you end up building and reach out if you have any questions, [@critesjosh\_](https://twitter.com/critesjosh_) on Twitter or joshc#0001 on Discord. Join the Celo discord at [https://chat.celo.org](https://chat.celo.org). diff --git a/blog/2022-01-06-web-dapp.md b/blog/2022-01-06-web-dapp.md new file mode 100644 index 0000000000..089e861889 --- /dev/null +++ b/blog/2022-01-06-web-dapp.md @@ -0,0 +1,408 @@ +--- +title: React based DApp +description: The basics of developing a decentralised application (DApp) on Celo. +slug: /developer-guide/start/web-dapp +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [DApp, react, nextjs, use-contractkit, sdk] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +# React Based DApp + +The basics of developing a decentralised application (DApp) on Celo. + + + +## Getting Started + +This example will develop using one of the core Celo contracts, [Governance.sol](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/Governance.sol), and allowing users of our DApp to vote on active [Celo Governance proposals](https://docs.celo.org/celo-owner-guide/voting-governance). + +## Foreword + +This guide requires an understanding of a few popular web technologies. Our application will be written in [React](https://reactjs.org/), utilising [hooks](https://reactjs.org/docs/hooks-intro.html) for state management and built with [Next.js](https://nextjs.org/), a popular static site generation framework. + +If you find this tutorial lacking in any way or want to dive into the code more thoroughly, checkout the [Celo Tools](https://github.com/alexbharley/celo-tools) GitHub repository where much of this tutorial has been ported from. + +## Getting started + +Step one of developing our application is scaffolding it out with `create-next-app` and adding TypeScript compilation so we can develop more confidently. + +```bash +yarn create next-app voting-dapp +cd voting-dapp +touch tsconfig.json +yarn add --dev typescript @types/react @types/node +``` + +Now running `yarn dev` should open up our new Next.js website on `localhost:3000`. + +Next we'll need to add a few Celo specific dependencies so we can work with our core contracts. + +```bash +yarn add @celo/contractkit @celo-tools/use-contractkit bignumber.js +``` + +Here's what we'll be using each of these packages for: + +- [@celo/contractkit](https://github.com/celo-org/celo-monorepo/tree/master/packages/sdk/contractkit) is a lightweight wrapper around the [Web3](https://web3js.readthedocs.io/) object you may already be familiar with. It contains typed interfaces for the core contracts (generated from the Contract ABIs) and helper functions to make common operations on Celo easier +- [@celo-tools/use-contractkit](https://github.com/celo-tools/use-contractkit) is a community provided library to ease establishing the connection with a user's wallet, whether that is a hardware, mobile, or web wallet. When developing with this library, your users can hold Celo via [Valora](https://valoraapp.com), a Ledger, Metamask and more +- [bignumber.js](https://github.com/MikeMcl/bignumber.js/) is a library for expressing large numbers in JavaScript. When interacting with a blockchain we often need to handle arbitrary-precision decimal and non-decimal arithmetic. + +We'll also need to add some Next.js config to work with these packages. Update next.config.js with the following: + +```javascript title="next.config.js" +module.exports = { + webpack: (config) => { + config.resolve.fallback = { + ...config.resolve.fallback, + fs: false, + net: false, + child_process: false, + readline: false, + }; + return config; + }, +}; +``` + +We'll need to restart the server for the config changes to take effect. + +## Developing the application + +After all our boilerplate has been setup, we're ready to start developing our application. + +### Connecting to the user's wallet + +When a user wants to interact with your DApp we need to somehow allow them to connect their wallet. Interaction with on chain smart contracts is impossible without this step. + +Leveraging our previously added [@celo-tools/use-contractkit](https://github.com/celo-tools/use-contractkit) library we can provide a button that prompts the user to connect their wallet. + +Update pages/index.js with the following: + +```javascript title="pages/index.js" +import React from "react"; +import { useContractKit } from "@celo-tools/use-contractkit"; +import { ContractKitProvider } from "@celo-tools/use-contractkit"; +import "@celo-tools/use-contractkit/lib/styles.css"; + +function App() { + const { address, connect } = useContractKit(); + + return ( +
+

Celo Voting DApp

+

{address}

+ +
+ ); +} + +function WrappedApp() { + return ( + + + + ); +} +export default WrappedApp; +``` + +Clicking this button will show the `use-contractkit` modal and allow the user to connect with their wallet of choice. Once the modal has been dismissed, the `address` property exposed by `use-contractkit` will be filled with the users primary account. + +### Accessing contracts + +After that we've connected to the user's wallet we can show interesting information based on their address. In the context of a governance voting DApp it may make sense to show past proposals they've voted on. If we were creating a simple banking interface, we could imagine wanting to show transfers into and out of the users account. + +:::info + +On the Celo blockchain, only queued and dequeued proposals are kept in the Governance state. That means to access old proposals we'd need to access an indexed history of the blockchain. This is out of scope for our tutorial however there's many resources online you can find that will help you accessing indexed blockchain state. + +For a comprehensive look at how to interpret this on chain state, take a look at the implementation for the [celocli governance:list](https://github.com/celo-org/celo-monorepo/blob/master/packages/cli/src/commands/governance/list.ts) command. + +For the purposes of this tutorial, we'll only be looking at dequeued proposals, or proposals we can currently vote on. + +::: + +Here's how it looks using a combination of the `useEffect` and `useCallback` hooks to request and display all dequeued proposals from the blockchain. + +```javascript title="pages/index.js" +import React, { useCallback, useEffect, useState } from "react"; +import { useContractKit } from "@celo-tools/use-contractkit"; + +function GovernanceApp() { + const { address, connect, kit, getConnectedKit } = useContractKit(); + const [proposals, setProposals] = useState([]); + + const fetchProposals = useCallback(async () => { + const governance = await kit.contracts.getGovernance(); + const dequeue = await governance.getDequeue(); + + const fetchedProposals = await Promise.all( + dequeue.map(async (id) => ({ + id, + ...(await governance.getProposalRecord(id)), + })) + ); + setProposals(fetchedProposals); + }, [kit]); + + useEffect(() => { + fetchProposals(); + }, [fetchProposals]); + + return ( +
+

Celo Voting DApp

+

{address}

+ + + + + + + + + + + {proposals.map((proposal) => ( + + + + + + ))} + +
IDStatusDescription URL
{proposal.id.toString()} + {proposal.passed + ? "Passed" + : proposal.approved + ? "Approved" + : "Not approved"} + + + Link + +
+
+ ); +} +``` + +Be sure to add this new `GovernanceApp` component to your `WrappedApp` component. + +```js title="pages/index.js" +function WrappedApp() { + return ( + + + + ); +} +``` + +This works pretty well however it makes sense to additionally show whether the user has voted on any given dequeued governance proposal. To show that information, we can amend our `fetchProposals` function as follows + +```js title="pages/index.js" +const fetchProposals = useCallback(async () => { + if (!address) { + return; + } + + const governance = await kit.contracts.getGovernance(); + const dequeue = await governance.getDequeue(); + + const fetchedProposals = await Promise.all( + dequeue.map(async (id) => { + const [record, voteRecord] = await Promise.all([ + governance.getProposalRecord(id), + governance.getVoteRecord(address, id), + ]); + + return { + id, + ...record, + vote: voteRecord ? voteRecord.value : undefined, + }; + }) + ); + setProposals(fetchedProposals); +}, [kit, address]); +``` + +Now we have access to whether the user voted on this proposal, we can render that information in our table. + +```js title="pages/index.js" +return ( + + + + + + + + + + + {proposals.map((proposal) => ( + + + + + + + ))} + +
IDStatusDescription URLVoted
{proposal.id.toString()} + {proposal.passed + ? "Passed" + : proposal.approved + ? "Approved" + : "Not approved"} + + + Link + + {proposal.vote ?? "No vote yet"}
+); +``` + +### Locking Celo (optional) + +A prerequisite to [voting on Celo governance proposals](/celo-owner-guide/voting-governance) is having locked Celo to vote with. We won't cover the various flows for locking, unlocking and relocking Celo in this tutorial but you can check the implementation in [Celo Tools](https://github.com/alexbharley/celo-tools) or take inspiration from the following script: + +```javascript +const lockValue = new BigNumber(res.flags.value); + +const lockedGold = await this.kit.contracts.getLockedGold(); +const pendingWithdrawalsValue = + await lockedGold.getPendingWithdrawalsTotalValue(address); +const relockValue = BigNumber.minimum(pendingWithdrawalsValue, value); +const lockValue = value.minus(relockValue); + +const txos = await lockedGold.relock(address, relockValue); +for (const txo of txos) { + await kit.sendAndWaitForReceipt({ from: address }); +} +``` + +All you need to take care of in your React application is handling user input to select the amount to lock and handling errors in case the user tries to lock more CELO than they hold. + +It's also possible that users of your DApp already have locked CELO, so you might not need to worry about the complexity of permitting that operation. + +### Voting on a proposal + +To actually vote on a proposal we need to again interact with the [Governance.sol](https://github.com/celo-org/celo-monorepo/blob/master/packages/protocol/contracts/governance/Governance.sol) smart contract. Our logic for handling a vote looks as follows: + +```typescript title="pages/index.js" +const vote = useCallback( + async (id: string, value: VoteValue) => { + const kit = await getConnectedKit(); + const governance = await kit.contracts.getGovernance(); + await (await governance.vote(id, value)).sendAndWaitForReceipt(); + fetchProposals(); + }, + [kit, fetchProposals] +); +``` + +How you handle calling that function is up to you. With [Celo Tools](https://github.com/alexbharley/celo-tools) we opted for simple upwards and downwards facing arrows to handle voting on proposals, however the data can be rendered however you'd prefer. + +Here's a simple example showing buttons for `Yes` or `No` votes when no vote has been cast. + +```javascript title="pages/index.js" +import { VoteValue } from "@celo/contractkit/lib/wrappers/Governance"; + +return ( + + {proposal.id.toString()} + + {proposal.passed + ? "Passed" + : proposal.approved + ? "Approved" + : "Not approved"} + + + + Description link + + + + {proposal.vote ? ( + {proposal.vote} + ) : ( +
+ + +
+ )} + + +); +``` + +## Best practices + +We've compiled a short list on best practices to follow when developing DApps. Following these will improve the end user experience and keep them more engaged with the Celo ecosystem. If you have any questions around these, feel free to [reach out on Discord](https://chat.celo.org), we're always there and happy to chat. + +### Last used address + +[@celo-tools/use-contractkit](https://github.com/celo-tools/use-contractkit) will remember the address a user last logged in with (via [browser LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)). Use this to your advantage and allow your DApp to display the same data whether or not the user has connected their wallet. A good test is to refresh your DApp after connecting and see if anything changes. At the very most, buttons for interaction could be disabled, however it's preferable to prompt to connect the wallet on button click. + +Keeping the UI consistent by using the last connected address is a quick win we can have with DApps that make the experience using them closer to Web2, an experience more users will be familiar with. + +### Loading states + +Loading times are often the give away that an application is a Web3 DApp. Be liberal with loading screens and prioritise making animations smooth. + +Nothing is worse than a perpetually hanging screen that takes multiple seconds to become interactive. By showing a spinner it communicates to the user that things are happening, however slow they may be. + +This is often offset by the ability to index a blockchain and provide the data in a more accessible format (maybe a SQL database or behind a GraphQL API). As mentioned earlier we haven't covered that in this tutorial, however there's a lot of content on the web around DApp optimisation through prior state indexing. + +### Prerender what you can + +With modern static site generators we have amazing leverage over what gets computed server side and what the browser has to request and compute before rendering. If you're unable to index the blockchain before a client requests access to a page, consider loading the relevant data server side with a cache invalidated every hour or so. + +Next.js [getStaticProps](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) comes to mind here as a great way to offload heavy computation to the server. + +### Showing numbers in wei vs. Celo vs. local currency + +Take this advice with a grain of salt as it really depends on how familiar with cryptocurrencies and blockchain your users are. At some point in most DApp users are going to need to deal with large numbers. It's up to you whether you display these in wei (1e18) CELO or converted to a currency the user prefers (BTC, USD or EUR for example). + +The sweeping generalisation would be to allow entering values in CELO or their preferred currency and never expose the raw wei amounts to end users. + +## Wrapping up + +Hopefully you have a better grasp on developing DApps against the Celo core contracts now. In this tutorial we covered: + +- Connecting to user wallets ([use-contractkit](https://github.com/celo-tools/use-contractkit)) +- Fetching on-chain data +- Calling simple functions on the core contracts +- A brief word on best practices with regard to DApp development. + +This is not a comprehensive tutorial for Celo's features and capabilities, keep exploring the docs to learn more and please [connect with us on Discord](https://chat.celo.org) if you need any help (or just want to chat)! diff --git a/blog/2022-01-07-on-chain-randomness.md b/blog/2022-01-07-on-chain-randomness.md new file mode 100644 index 0000000000..d0cca15dbd --- /dev/null +++ b/blog/2022-01-07-on-chain-randomness.md @@ -0,0 +1,49 @@ +--- +title: "Use onchain randomness" +description: How to use onchain randomness in your smart contracts. +slug: /developer-guide/start/randomness +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [solidity, randomness, oracle] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +import PageRef from '@components/PageRef'; + +Onchain randomness is used for selecting validators to perform phone number verification. Read more about how onchain randomness is produced at the provided page. + + + + + +This randomness can be used by any smart contracts deployed to a Celo network. + +```solidity +import "celo-monorepo/packages/protocol/identity/interfaces/IRandom.sol"; +import "celo-monorepo/packages/protocol/common/interfaces/IRegistry.sol"; + +contract Example { + function test() external view returns (bytes32 randomness) { + randomness = IRandom( + IRegistry(0x000000000000000000000000000000000000ce10) + .getAddressFor(keccak256(abi.encodePacked("Random"))) + ).random(); + } +} +``` + +Alternatively, through inheritance of `UsingRegistry`. + +```solidity +import "celo-monorepo/packages/protocol/common/UsingRegistryV2.sol"; + +contract Example is UsingRegistryV2 { + function test() external view returns (bytes32 randomness) { + randomness = getRandom().random(); + } +} +``` diff --git a/blog/2022-01-08-valora-wc-v1.md b/blog/2022-01-08-valora-wc-v1.md new file mode 100644 index 0000000000..06f1520989 --- /dev/null +++ b/blog/2022-01-08-valora-wc-v1.md @@ -0,0 +1,132 @@ +--- +title: Celo Valora + WalletConnect v1 +description: How to use Wallet Connect version 1 in a DApp to connect to Valora. +authors: + - name: Josh Crites + title: Developer Relations, cLabs + url: https://github.com/critesjosh + image_url: https://github.com/critesjosh.png +tags: [react, valora, wallet connect] +image: https://dl.airtable.com/.attachmentThumbnails/a7e530eb72ac8f30f37c0a3447ef0e7d/72e944da +hide_table_of_contents: false +--- + +import ImageWrapper from '@components/ImageWrapper' + +# Valora + WalletConnect v1 + +How to use [WalletConnect version 1](https://docs.walletconnect.com/1.0/) in a DApp to connect to [Valora](https://valoraapp.com/). + + + +## Getting Started + +In this example, we will demonstrate how to add WalletConnect to a simple React app. + +This is a simple DApp that focuses on demonstrating how to connect WalletConnect to Valora, but also shows how to set up [ContractKit](/developer-guide/contractkit) and make a simple cUSD transfer. You can view the DApp code [here](https://github.com/critesjosh/valora-wallet-connect-v1). + +## Add Packages + +Add the packages that you need to your project. + +- [@walletconnect/web3-provider](https://www.npmjs.com/package/@walletconnect/web3-provider) +- [Contractkit](https://www.npmjs.com/package/@celo/contractkit) +- [Web3](https://www.npmjs.com/package/web3) + +```shell +yarn add @wallet-connect/web3-provider web3 @celo/contractkit +``` + +Import the packages to your project code. + +```js +import WalletConnectProvider from "@walletconnect/web3-provider"; +import Web3 from "web3"; +import { newKitFromWeb3 } from "@celo/contractkit"; +``` + +## Connect + +If the DApp does not detect a [wallet connect provider](https://docs.walletconnect.com/1.0/quick-start/dapps/web3-provider), the user will be presented with a button to initiate a wallet connection. + +If the DApp is being accessed on a computer or device other than the mobile device with the wallet, the user can connect to the mobile wallet by scanning the presented QR code. If the DApp is being accessed on the same device as the wallet, the connection will be made via the appropriate linking mechanism (iOS and Android are different). You can read more about that [here](https://docs.walletconnect.com/1.0/mobile-linking#wallet-support). + +When a provider is detected, the DApp will show a button to send some cUSD. + +![connect dapp](/img/doc-images/valora-wc-v1/connect-dapp.png) + +The connect function sets up the WalletConnect Provider and initializes ContractKit with the provider and user account. It also sets up a listener that will log when the user changes accounts. The DApp then saves the provider and initialized Contractkit in the [React component state](https://reactjs.org/docs/faq-state.html). + +```js +connect = async () => { + const provider = new WalletConnectProvider({ + rpc: { + 44787: "https://alfajores-forno.celo-testnet.org", + 42220: "https://forno.celo.org", + }, + }); + + await provider.enable(); + const web3 = new Web3(provider); + let kit = newKitFromWeb3(web3); + + kit.defaultAccount = provider.accounts[0]; + + provider.on("accountsChanged", (accounts) => { + console.log(accounts); + }); + + this.setState({ provider, kit }); +}; +``` + +**DApp:** + +![qr code](/img/doc-images/valora-wc-v1/qr-code.png) + +**Valora:** + + + +When the provider has been set and the DApp is connected to Valora, the UI will update the button and display the user account address below. + +![send cusd](/img/doc-images/valora-wc-v1/send-cusd.png) + +## Send cUSD + +Clicking the new button will prompt the user to send 0.001 cUSD to a hard-coded address. The user will have to click Allow to send the transaction. Once the transaction is confirmed, the transaction receipt will be printed in the DApp browser console. + +You can code the transaction approval request with just a few lines, demonstrated in the `sendcUSD` function. + +- Get the saved instance of ContractKit from `this.state.kit` +- Get the stabletoken (cUSD) contract +- Call `transfer` and `send` with the recipient and amount + +```js +sendcUSD = async () => { + let kit = this.state.kit; + + let amount = kit.web3.utils.toWei("0.001", "ether"); + + const stabletoken = await kit.contracts.getStableToken(); + const tx = await stabletoken.transfer(this.state.someAddress, amount).send(); + const receipt = await tx.waitReceipt(); + + console.log(receipt); +}; +``` + + + +The receipt will be logged once the user approves the transaction and it is confirmed on the network. + +## Pay Fees in Stable currencies + +Specifying the `feeCurrency` field in the transaction will allow users to pay transaction fees in that currency. Here's how you can have users pay transaction fees in cUSD, for example: + +```js +const stabletoken = await kit.contracts.getStableToken(); +let tx = await stabletoken + .transfer(this.state.someAddress, amount) + .send({ feeCurrency: stabletoken.address }); +``` diff --git a/docs/community/join-the-community.md b/docs/community/join-the-community.md index e39511a89a..c1b63c9bfc 100644 --- a/docs/community/join-the-community.md +++ b/docs/community/join-the-community.md @@ -9,7 +9,7 @@ Find Celo on social media, contribute to the codebase, or chat with the communit --- -## Follow +## Social Media Follow on Social Media to learn more about Celo. @@ -25,7 +25,7 @@ Follow on Social Media to learn more about Celo. - [Reddit](https://www.reddit.com/r/celo/) - [Telegram](https://t.me/celoplatform) -## Connect +## Discussions Ask questions, find answers, and get in touch. @@ -35,7 +35,7 @@ Ask questions, find answers, and get in touch. - [Celo Website](https://celo.org/build) - [Host a Meetup](https://airtable.com/shrTCM7LddTxOm3r6) -## Contribute +## Contributions Browse the code, raise an issue, or contribute a pull request. diff --git a/docs/developer-resources/contractkit/index.md b/docs/developer-resources/contractkit/index.md index d45fa619ee..c889c924df 100644 --- a/docs/developer-resources/contractkit/index.md +++ b/docs/developer-resources/contractkit/index.md @@ -3,25 +3,28 @@ title: Celo ContractKit description: Overview of ContractKit, its features, purpose, and resources to help you get started. slug: /developer-guide/contractkit --- + import PageRef from '@components/PageRef' # ContractKit Overview of ContractKit, its features, purpose, and resources to help you get started. -___ +--- ## What is ContractKit? -ContractKit is a library to help developers and validators to interact with the celo-blockchain and is well suited to developers looking for an easy way to integrate Celo Smart Contracts within their applications. +ContractKit is a library to help developers and validators to interact with the Celo blockchain and is well suited to developers looking for an easy way to integrate Celo Smart Contracts within their applications. + +Contractkit includes common functionality to make it easier to get started building. -## What you can do? +**What you can do?** -ContractKit supports the following functionality: +[ContractKit](../community/release-process/base-cli-contractkit-dappkit-utils) supports the following functionality: - Connect to a node -- Access web3 object to interact with node's Json RPC API -- Send Transaction with celo's extra fields: (feeCurrency, gatewayFeeRecipient and gatewayFee) +- Access Web3 object to interact with node's JSON RPC API +- Send Transaction with Celo's extra fields: (feeCurrency, gatewayFeeRecipient, and gatewayFee) - Simple interface to interact with CELO and cUSD - Simple interface to interact with Celo Core contracts - Local sign transactions diff --git a/docs/developer-resources/deploy-dapp.md b/docs/developer-resources/deploy-dapp.md index c2970c16f3..c32023a62e 100644 --- a/docs/developer-resources/deploy-dapp.md +++ b/docs/developer-resources/deploy-dapp.md @@ -1,43 +1,29 @@ --- -title: Build on Celo -description: How to set up your development environment and deploy on Celo. +title: Deploy on Celo +description: How to deploy a dApp on Celo. --- import PageRef from '@components/PageRef' -# Build on Celo +# Deploy on Celo -How to set up your development environment and deploy on Celo. +How to deploy a dApp on Celo. -___ +--- -The fastest way to build and deploy on Celo is to [Set up a Testnet Development Wallet](./testnet-wallet.md) and [Deploy with Remix](./deploy-remix.md). This doesn’t require installing anything on your local device and gives you access to powerful web-based tools for dApp development. Alternatively, you can set up a local development environment and deploy using many popular dApp deployment tools. +The fastest way to deploy on Celo is to [Set up a Testnet Development Wallet](./testnet-wallet.md) and [Deploy with Remix](./deploy-remix.md). This doesn’t require installing anything on your local device and gives you access to powerful web-based tools for dApp development. Alternatively, you can set up a local development environment and deploy using many popular dApp deployment tools. :::tip -Developers can build on Celo using many [Ethereum](https://ethereum.org/en/) compatible tools including Remix, Truffle, Hardhat, and others. By making a few adjustments to your project’s network configuration settings, you can deploy your new or existing dApp on Celo. +Developers can build on Celo using many [Ethereum](https://ethereum.org/en/) compatible tools including Remix, Truffle, Hardhat, and others. By making a few adjustments to your project’s network configuration settings, you can deploy your new or existing dApp on Celo. Just getting started learning about how to write smart contracts? [The Solidity docs](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html) are a great place to start. ::: -## Set up your local environment - - - - -## Set up a development wallet - - - - ## Deploy on Celo - -## Code Examples - - diff --git a/docs/developer-resources/ethers-js-wrapper.md b/docs/developer-resources/ethers-js-wrapper.md new file mode 100644 index 0000000000..754d43ef69 --- /dev/null +++ b/docs/developer-resources/ethers-js-wrapper.md @@ -0,0 +1,99 @@ +--- +title: Celo Ethers.js Wrapper +description: A minimal wrapper to make Ethers.JS compatible with the Celo network. +--- + +# Celo Ethers.JS Wrapper + +A minimal wrapper to make Ethers.JS compatible with the Celo network. + +--- + +:::tip + +This is still experimental. [View on GitHub](https://github.com/celo-tools/celo-ethers-wrapper) + +::: + +## Install + +`npm i @celo-tools/celo-ethers-wrapper` + +or + +`yarn add @celo-tools/celo-ethers-wrapper` + +Note this wrapper has Ethers v5 as a peer dependency. Your project must include a dependency on that as well. + +## Basic Usage + +Connect to the network by creating a `CeloProvider`, which is based on [JsonRpc-Provider](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/): + +```js +import { CeloProvider } from "@celo-tools/celo-ethers-wrapper"; + +// Connecting to Alfajores testnet +const provider = new CeloProvider("https://alfajores-forno.celo-testnet.org"); +await provider.ready; +``` + +Note: for a more efficient provider based on [StaticJsonRpcProvider](https://docs.ethers.io/v5/api/providers/jsonrpc-provider/#StaticJsonRpcProvider) you can use `StaticCeloProvider` instead. + +Next, Create a CeloWallet, which is based on [Wallet](https://docs.ethers.io/v5/api/signer/#Wallet) : + +```js +import { CeloWallet } from "@celo-tools/celo-ethers-wrapper"; + +const wallet = new CeloWallet(YOUR_PK, provider); +``` + +Use the provider or wallet to make calls or send transactions: + +```js +const txResponse = await wallet.sendTransaction({ + to: recipient, + value: amountInWei, +}); +const txReceipt = await txResponse.wait(); +console.info(`CELO transaction hash received: ${txReceipt.transactionHash}`); +``` + +## Contract Interaction + +`CeloWallet` can be used to send transactions. + +Here's an example of sending cUSD with the StableToken contract. For interacting with contracts you need the ABI and address. Addresses for Celo core contracts can be found with the CLI's `network:contracts` command. The ABIs can be built from the solidity code or extracted in ContractKit's `generated` folder. + +```js +import { Contract, ethers, utils, providers } from "ethers"; + +const stableToken = new ethers.Contract(address, abi, wallet); +console.info(`Sending ${amountInWei} cUSD`); +const txResponse: providers.TransactionResponse = + await stableToken.transferWithComment(recipient, amountInWei, comment); +const txReceipt = await txResponse.wait(); +console.info(`cUSD payment hash received: ${txReceipt.transactionHash}`); +``` + +## Alternative gas fee currencies + +The Celo network supports paying for transactions with the native asset (CELO) but also with the stable token (cUSD). + +This wrapper currently has partial support for specifying feeCurrency in transactions. + +```js +const gasPrice = await wallet.getGasPrice(stableTokenAddress); +const gasLimit = await wallet.estimateGas(tx); + +// Gas estimation doesn't currently work properly for non-CELO currencies +// The gas limit must be padded to increase tx success rate +// TODO: Investigate more efficient ways to handle this case +const adjustedGasLimit = gasLimit.mul(10); + +const txResponse = await signer.sendTransaction({ + ...tx, + gasPrice, + gasLimit: adjustedGasLimit, + feeCurrency: stableTokenAddress, +}); +``` diff --git a/docs/developer-resources/integrations/integrations.md b/docs/developer-resources/integrations/integrations.md index 5dcfd1c96c..5e88edfa15 100644 --- a/docs/developer-resources/integrations/integrations.md +++ b/docs/developer-resources/integrations/integrations.md @@ -1,5 +1,5 @@ --- -title: Celo Integrations +title: Integrate with Celo description: Collection of resources to help integrate Celo with your service. slug: /developer-guide/integrations --- @@ -8,11 +8,11 @@ import PageRef from '@components/PageRef' import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Celo Integrations +# Integrate with Celo Collection of resources to help integrate Celo with your service. -___ +--- Celo provides you with the tools to easily integrate DeFi into your existing mobile application or blockchain service. Integrating with Celo allows you to accept payments, send payouts, and manage all of your DeFi needs using our global financial infrastructure. @@ -35,4 +35,3 @@ Not ready to Integrate with Celo? [Learn more about Celo](/welcome.md). For questions, comments, and discussions please use the [Celo Forum](https://forum.celo.org/) or [Discord](https://chat.celo.org/). ::: - diff --git a/docs/developer-resources/networks/alfajores-testnet.md b/docs/developer-resources/networks/alfajores-testnet.md new file mode 100644 index 0000000000..6066cea2d1 --- /dev/null +++ b/docs/developer-resources/networks/alfajores-testnet.md @@ -0,0 +1,12 @@ +--- +title: Alfajores Testnet +--- + +# Alfajores Testnet + +The [Alfajores Testnet](/getting-started/alfajores-testnet) is a Celo test network for developers building on the Celo platform. You can use it to try out the[ Celo Wallet](https://celo.org/build/wallet) or the Celo CLI (by sending transfers to yourself or other users of the testnet). You can also assist in running the network by operating a full node on your machine (or on a cloud or hosting provider). + +- [Alfajores Testnet Faucet](https://celo.org/build/faucet) - get testnet tokens to experiment with +- [Celo Wallet for Alfajores](https://celo.org/build/wallet) - download the Android wallet app for the testnet from the Play Store +- [Alfajores Network Status](https://alfajores-celostats.celo-testnet.org/) - to check the current availability of the testnet +- [Alfajores Testnet Block Explorer](https://alfajores-blockscout.celo-testnet.org/) - explore the history of the blockchain and view transaction details diff --git a/docs/developer-resources/networks/baklava-testnet.md b/docs/developer-resources/networks/baklava-testnet.md new file mode 100644 index 0000000000..cec9673fc3 --- /dev/null +++ b/docs/developer-resources/networks/baklava-testnet.md @@ -0,0 +1,13 @@ +--- +title: Baklava Testnet +--- + +### Baklava Testnet + +The [Baklava Testnet](/getting-started/baklava-testnet) is focused on building operational experience and best practices for node operators. + +It is designed for validators and testing protocol changes. You will most likely not develop on the Baklava testnet. If you have an idea for a project that uses more protocol features in terms of handling the community fund or uniquely handling epoch rewards, like block rewards or staking rewards, it might be useful to develop on Baklava. + +- [Baklava Faucet Request Form](https://forms.gle/JTYkMAJWTAUQp1sv9) - to request faucetted funds to become a Validator on the Baklava network. +- [Baklava Network Status](https://baklava-celostats.celo-testnet.org/) - to check the current availability of the testnet +- [Baklava Network Block Explorer](https://baklava-blockscout.celo-testnet.org/) - explore the history of the blockchain and view transaction details diff --git a/docs/developer-resources/networks/celo-mainnet.md b/docs/developer-resources/networks/celo-mainnet.md new file mode 100644 index 0000000000..7fba2990ee --- /dev/null +++ b/docs/developer-resources/networks/celo-mainnet.md @@ -0,0 +1,11 @@ +--- +title: Celo Mainnet +--- + +# Celo Mainnet + +The production Celo network, [Mainnet](/getting-started/mainnet) was previously known as the Release Candidate 1 network. Deployed by the Celo community starting 4/22/20, the network is currently working towards enabling the Celo stability mechanism. Much of the activity is being driven by the validator organizations that are featured on the leaderboard of[ The Great Celo Stake Off](https://forum.celo.org/t/the-great-celo-stake-off-the-details/136). + +- [Mainnet Validator Explorer](https://validators.celo.org/) - to view the current status of Validator elections +- [Mainnet Network Status](https://stats.celo.org/) - to check the current availability of the network +- [Mainnet Network Block Explorer](http://explorer.celo.org/) - explore the history of the blockchain and view transaction details diff --git a/docs/developer-resources/overview.md b/docs/developer-resources/overview.md index 76c6547ede..9efb93d5c9 100644 --- a/docs/developer-resources/overview.md +++ b/docs/developer-resources/overview.md @@ -2,20 +2,19 @@ title: Celo Developers Overview description: There are 6 Billion smartphones on Earth. Build for all of them. slug: /developer-guide/overview - --- import PageRef from '@components/PageRef' import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Celo Developers +# Build on Celo There are 6 Billion smartphones on Earth. Build for all of them. -___ +--- -[Celo Developers](https://celo.org/developers) build financial dApps that create the conditions for prosperity for everyone. Celo's ultralight mobile client makes it easy to build for smartphones across the world. Send or Request stable assets easily with anyone in your address book, powered by decentralized phone number verification. +[Celo Developers](https://celo.org/developers) build financial dApps that create the conditions for prosperity for everyone. Celo's ultralight mobile client makes it easy to build for smartphones across the world. Send or Request stable assets easily with anyone in your address book, powered by decentralized phone number verification. :::tip @@ -23,24 +22,28 @@ Not ready to become a Celo Developer? [Learn more about Celo](../../docs/welcome ::: -## Build on Celo +## Set up your environment -Get started, learn how to deploy contracts, and more. + + - +:::info +Want to create a dApp fast? [Deploy on Celo](/developer-resources/deploy-dapp) + +::: -## Code for the EVM +## Create a testnet wallet -Celo is Ethereum Virtual Machine (EVM) compatible making it easy to build and port dApps over. + - +## Deploy on Celo -## Use your favorite tools + -Celo works with native mobile dApps and is interoperable with MetaMask and popular Ethereum developer tools. +## Integrate with Celo - + :::tip diff --git a/docs/developer-resources/testnet-wallet.md b/docs/developer-resources/testnet-wallet.md index 932c9795e5..af63d2a8be 100644 --- a/docs/developer-resources/testnet-wallet.md +++ b/docs/developer-resources/testnet-wallet.md @@ -1,13 +1,14 @@ --- -title: Setup Testnet Wallet -description: How to create and fund a wallet to use for developing Celo dApps. +title: Setup Testnet Wallets +description: How to create and fund testnet wallets to use for developing Celo dApps. --- -# Setup Testnet Wallet +# Testnet Wallets -How to create and fund a wallet to use for developing Celo dApps. +How to create and fund a testnet wallets to use for developing Celo dApps. + +--- -___ ## Getting Started While developing and deploying dApps on Celo, it’s helpful to have a wallet prepared with funds to pay for any transactions you make on the blockchain. These can be set up using either real or test funds, and this allows application developers and users to interact Celo applications more easily. @@ -81,7 +82,7 @@ Skip to [this step](#import-account-to-wallet-for-options-2--3) to connect your ### Using Celo CLI -Install `celocli` by running +Install `celocli` by running ``` npm install -g @celo/celocli @@ -111,7 +112,7 @@ Skip to [this step](#import-account-to-wallet-for-options-2--3) to connect your ## Import Account to Wallet (for Options 2 & 3) -If you created an account using option 2 or 3, you can now import these accounts to your wallet. +If you created an account using option 2 or 3, you can now import these accounts to your wallet. - Open your wallet browser extension from your browser - Select **Settings** > **Import Account** diff --git a/docs/developer-resources/use-contractkit.md b/docs/developer-resources/use-contractkit.md new file mode 100644 index 0000000000..3a86bcc6d0 --- /dev/null +++ b/docs/developer-resources/use-contractkit.md @@ -0,0 +1,243 @@ +--- +title: use-contractkit +description: The easiest way to access [ContractKit](https://www.npmjs.com/package/@celo/contractkit) in your React applications. +--- + +# use-contractkit + +The easiest way to access [ContractKit](https://www.npmjs.com/package/@celo/contractkit) in your React applications. + +--- + +## What is use-contractkit? + +The easiest way to access [ContractKit](https://www.npmjs.com/package/@celo/contractkit) in your React applications 🔥. `use-contractkit` is a [React hook](https://reactjs.org/docs/hooks-intro.html) for managing access to ContractKit with a built-in headless modal system for connecting to your users wallet of choice. + +Now your DApp can be made available to everyone in the Celo ecosystem, from Valora users to self custodied Ledger users. + +By default use-contractkit is styled so that you can drop it into your application and go, however it's fully customisable so you can maintain a consistent UX throughout your application. + +## Table of Contents + +- [Installation](#install) +- [Supported Wallets](#supported-wallets) +- [Usage](#usage) +- [Notes](#notes) +- [Support](#support) + +## Install + +``` +yarn add @celo-tools/use-contractkit +``` + +## Supported wallets + +| Wallet | sendTransaction | signTransaction | signTypedData | signPersonal | +| ------------------------------------------------------------------------------------------ | :----------------: | -----------------: | ------------------ | ------------------ | +| Plaintext private key | | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Ledger](https://www.ledger.com/) | | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [WalletConnect](https://walletconnect.org/) | | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Celo Extension Wallet (Metamask fork)](https://github.com/dsrvlabs/celo-extension-wallet) | :white_check_mark: | | | | + +## Basic Usage + +### Wrap your application with ContractKitProvider + +use-contractkit uses [unstated-next](https://github.com/jamiebuilds/unstated-next) under the hood to inject state throughout your application. unstated-next is built on top of the React Context API so you need to make sure your application is wrapped with the provider before usage. + +```jsx +import { ContractKitProvider } from "@celo-tools/use-contractkit"; +import "@celo-tools/use-contractkit/lib/styles.css"; + +function WrappedApp() { + return ( + + + + ); +} + +function App() { + // your application code +} +``` + +### Prompt users to connect their wallet + +use-contractkit provides a `connect` function that will open a modal with a list of wallets your user can connect to. + +```jsx +import { useContractKit } from "@celo-tools/use-contractkit"; + +function App() { + const { connect, address } = useContractKit(); + + return ( + <> + {address ? ( +
Connected to {address}
+ ) : ( + + )} + + ); +} +``` + +After connecting to an account the `address` property will be set. + +### Use ContractKit to read chain data + +Now that we've connected to an account and have the users address, we can use the `kit` to query on-chain data: + +```jsx +import { useContractKit } from '@celo-tools/use-contractkit'; + +function App() { + const { kit, address } = useContractKit(); + + async function getAccountSummary() { + const accounts = await kit.contracts.getAccounts(); + await accounts.getAccountSummary(address); + } + + return ( + ... + ) +} +``` + +### Accessing user accounts + +The biggest problem when developing DApps is ensuring a Web2 level experience while managing the flaky and often slow nature of blockchains. To that end we've designed use-contractkit in a way to abstract away most of that pain. + +Initially connecting to a users account is one thing, handled via the `connect` function we just mentioned. However once a user has connected to your DApp once we can make the experience nicer for them on repeat visits. + +#### Last connected account + +use-contractkit will remember a users last connected address when they navigate back to or refresh your DApp. Ensure that when developing your DApp nothing changes nothing in the UI whether or not the user has a `kit.defaultAccount` property set. + +```javascript +import { useContractKit } from "@celo-tools/use-contractkit"; + +const { address } = useContractKit(); +``` + +#### Get a connected account + +When a user refreshes or navigates back to your page, they may not necessarily have a connected account any longer, however we shouldn't need to prompt them to login again just to view the page, that can be done only when doing an action. + +For that functionality we have the `performActions` and `getConnectedKit` methods. Usage looks a little like this for `getConnectedKit`: + +```jsx +import { useContractKit } from "@celo-tools/use-contractkit"; + +function App() { + const { getConnectedKit } = useContractKit(); + + async function transfer() { + const kit = await getConnectedKit(); + const cUSD = await kit.contracts.getStableToken(); + await cUSD.transfer("0x...", 10000).sendAndWaitForReceipt(); + } + + return ; +} +``` + +and this for `performActions`: + +```jsx +import { useContractKit } from "@celo-tools/use-contractkit"; + +function App() { + const { performActions } = useContractKit(); + + async function transfer() { + await performActions(async (kit) => { + const cUSD = await kit.contracts.getStableToken(); + await cUSD.transfer("0x...", 10000).sendAndWaitForReceipt(); + }); + } + + return ; +} +``` + +The `performActions` method will also take care of displaying a modal to the user telling them to confirm any actions on their connected wallet. + +### Network management + +use-contractkit provides a `network` variable and an `updateNetwork` function you can use to display the currently connected network as well as switch to a different one (ie. Alfajores, Baklava or Mainnet). + +If you'd prefer your DApp to only access a specific network (maybe you're deploying your testnet website at `https://test-app.dapp.name` and your mainnet version at `https://app.dapp.name`) you can pass the network you want to use as a variable into the provider you wrap your application with: + +You can also pass in a `network` prop to the `ContractKitProvider` as the default starting network + +```jsx +import { ContractKitProvider, Alfajores } from '@celo-tools/use-contractkit'; + +function WrappedApp({ Component, pageProps }) { + return ( + + + + ); +} + +function App () { + ... +} +``` + +Be sure to check the use-contractkit example application for a showcase of how network management works in more depth. Usually you'll want to show a dropdown to your users allowing them to select the network to connect to. + +```jsx +import { useContractKit } from "@celo-tools/use-contractkit"; + +function App() { + const { network, updateNetwork } = useContractKit(); + + return
Currently connected to {network}
; +} +``` + +### Adjust FeeCurrency + +use-contractkit provides a `feeCurrency` variable and an `updateFeeCurrency` function you can use to display the currently selected feeCurrency (cUSD, CELO, cEUR). The feeCurrency can also be passed to the provider component. Valid values are `CeloContract.GoldToken`, `CeloContract.StableToken`, `CeloContract.StableTokenEUR`. CeloContract can be imported like so: + +`import { CeloTokenContract } from '@celo/contractkit'` + +### Dark mode + +use-contrackit uses Tailwind for styling, to use the modal in dark mode simply add the class `tw-dark` to the root `` tag of the web page. + +## Development + +To run use-contractkit locally, simply clone this repository and run: + +- `yarn` +- `make dev` + +A hot reloading server should come up on `localhost:3000`, it's the exact same as what's at [use-contractkit-c-labs.vercel.app](https://use-contractkit-c-labs.vercel.app). + +## Support + +Struggling with anything use-contractkit related? Jump into the [celo-org discord channel](https://chat.celo.org) and ask for help any time. diff --git a/docs/learn/developer-tools.md b/docs/learn/developer-tools.md index 065801dd6e..cf15d1e3f4 100644 --- a/docs/learn/developer-tools.md +++ b/docs/learn/developer-tools.md @@ -2,13 +2,16 @@ title: Celo Developer Tools description: Overview of Celo tools and the value they provide to developers. --- + # Developer Tools Overview of Celo tools and the value they provide to developers. -___ +--- -## SDKs +import PageRef from '@components/PageRef' +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; :::tip @@ -16,91 +19,79 @@ Consider using [Dependabot](https://docs.github.com/en/code-security/supply-chai ::: +## SDKs + ### ContractKit ContractKit is a library to help developers and validators to interact with the Celo blockchain and is well suited to developers looking for an easy way to integrate Celo Smart Contracts within their applications. -Contractkit includes common functionality to make it easier to get started building + -**What you can do?** +### use-contractkit -[ContractKit](../community/release-process/base-cli-contractkit-dappkit-utils) supports the following functionality: +[use-contractkit](https://github.com/celo-tools/use-contractkit) is [Web3Modal](https://web3modal.com/)-like experience that injects ContractKit into your web-based application. Supports a variety of different wallets, including but not limited to Valora, Ledger, Metamask (Celo compatible fork) and any WalletConnect compatible wallets -* Connect to a node -* Access Web3 object to interact with node's JSON RPC API -* Send Transaction with Celo's extra fields: (feeCurrency, gatewayFeeRecipient, and gatewayFee) -* Simple interface to interact with CELO and cUSD -* Simple interface to interact with Celo Core contracts -* Local sign transactions -* Utilities -* Query on-chain identifier for a phone number + -### Celo Ethers.js Wrapper +### Ethers.JS Wrapper -[Celo Ethers.js Wrapper](https://github.com/celo-tools/celo-ethers-wrapper) is a minimal wrapper to make [ethers.js](https://docs.ethers.io/v5/) compatible with the Celo network +A minimal wrapper to make Ethers.JS compatible with the Celo network. -### use-contractkit + -[use-contractkit](https://github.com/celo-tools/use-contractkit) is [Web3Modal](https://web3modal.com/)-like experience that injects ContractKit into your web-based application. Supports a variety of different wallets, including but not limited to Valora, Ledger, Metamask (Celo compatible fork) and any WalletConnect compatible wallets +### WalletConnect -### Celo CLI +WalletConnect is a standard across EVM compatible blockchains to connect wallets to dapps. It allows developers to build connections between wallets and dapps on the same desktop or mobile device, or between desktop dapps and mobile wallets. -The [Command-Line Interface](../community/release-process/base-cli-contractkit-dappkit-utils) allows users to interact with the Celo Protocol smart contracts. + -It’s a command-line interface around the ContractKit. It allows you to interact with the Celo Protocol and smart contracts using command-line tools rather than writing JavaScript. It provides modules for interacting with modules on the ContractKit and is an excellent code reference when defining your own modules. Some common features you may want to consider are helping users participate in elections or in on-chain governance, voting for validators, or helping users interact with multi-sig contracts. +### DAppKit -## WalletConnect +DAppKit is a lightweight set of functions that allow mobile DApps to work with the Celo Wallet to sign transactions and access the user's account. -[WalletConnect](https://walletconnect.com/) is a standard across EVM compatible blockchains to connect wallets to dapps. It allows developers to build connections between wallets and dapps on the same desktop or mobile device, or between desktop dapps and mobile wallets. + -## DAppKit +### Celo CLI -:::warning +The Command Line Interface allows users to interact with the Celo Protocol smart contracts. -While DAppKit is functional, it is no longer being actively maintained in favor of WalletConnect. If WalletConnect does not work for your use case, you can use deep links directly. You can read more about how Valora handles this [here](https://github.com/valora-inc/wallet/blob/main/packages/mobile/docs/deeplinks.md). + -::: +## Infrastructure + +### BlockScout -[DAppKit](../developer-guide/dappkit) is a lightweight set of functions that allow mobile dApps to work with the Celo Wallet to sign transactions and access the user's account. This allows for a better user experience: DApps can focus on a great native experience without having to worry about key management. It also provides a simpler development experience, as no state or connection management is necessary. +[BlockScout](https://explorer.celo.org/) is a cLabs hosted GUI block explorer and [API endpoints](https://explorer.celo.org/api_docs). It allows you to look up information about the Celo blockchain including average block time, total transactions, and additional transaction details. You may also view details of your own custom smart contracts or existing DeFi contracts to view how value is moving between accounts and on-chain network events. -**DAppKit supports the following functionality:** + -* Request permission to access account information and phone number from the Celo Wallet -* Request permission to sign the transaction(s) from the Celo Wallet -* Look up phone numbers using the Identity Protocol to find contacts using Celo. +### ODIS -DAppKit is currently built with React Native in mind, though the excellent[ Expo framework](https://expo.io/) is still highly recommended for developers building mobile and web dApps on Celo. Expo offers awesome features like incredibly easy setup, hot-reloading, and more. Currently, most of our tutorials and examples involve Expo, though we are working on creating additional documentation for other app frameworks. While DAppKit was designed for mobile apps in particular, since version 1.1.0-beta.1 it offers beta support for web dApps running in the browser of a mobile device. More details about this are included in the Usage section below. +[ODIS](/developer-resources/contractkit/odis.md) (Oblivious decentralized identity service) is a lightweight identity layer that makes it easy to send cryptocurrency to a phone number -## Celo Networks + -### Mainnet +### The Graph -The production Celo network, [Mainnet](../getting-started/mainnet) was previously known as the Release Candidate 1 network. Deployed by the Celo community starting 4/22/20, the network is currently working towards enabling the Celo stability mechanism. Much of the activity is being driven by the validator organizations that are featured on the leaderboard of[ The Great Celo Stake Off](https://forum.celo.org/t/the-great-celo-stake-off-the-details/136). +[The Graph](https://thegraph.com/) is an indexing protocol for querying networks like Celo, Ethereum and IPFS. Anyone can build and publish open APIs, called subgraphs, making data easily accessible. Many blockchain data querying tools like Dapplooker leverage the Graph. You can read more about how to use the Graph with Celo [here](/blog/using-the-graph). -* [Mainnet Validator Explorer](https://validators.celo.org/) - to view the current status of Validator elections -* [Mainnet Network Status](https://stats.celo.org/) - to check the current availability of the network -* [Mainnet Network Block Explorer](http://explorer.celo.org/) - explore the history of the blockchain and view transaction details + -### Alfajores Testnet +### DappLooker -The [Alfajores Testnet](../getting-started/alfajores-testnet) is a Celo test network for developers building on the Celo platform. You can use it to try out the[ Celo Wallet](https://celo.org/build/wallet) or the Celo CLI (by sending transfers to yourself or other users of the testnet). You can also assist in running the network by operating a full node on your machine (or on a cloud or hosting provider). +[DappLooker](https://dapplooker.com/integration/celo) allows you to easily analyze & visualize your Celo smart contracts & subgraph data in various formats and gather it into dashboards from multiple sources. Analyze your data with intuitive Visual SQL which writes queries for you. Share the story your data tells with your team or with your community. Share dashboard insights via URL wherever you need to make your organization truly data driven. -* [Alfajores Testnet Faucet](https://celo.org/build/faucet) - get testnet tokens to experiment with -* [Celo Wallet for Alfajores](https://celo.org/build/wallet) - download the Android wallet app for the testnet from the Play Store -* [Alfajores Network Status](https://alfajores-celostats.celo-testnet.org/) - to check the current availability of the testnet -* [Alfajores Testnet Block Explorer](https://alfajores-blockscout.celo-testnet.org/) - explore the history of the blockchain and view transaction details + -### Baklava Testnet +### Stats.celo.org -The [Baklava Testnet](../getting-started/baklava-testnet) is focused on building operational experience and best practices for node operators. +[Stats.celo.org](http://stats.celo.org) allows you to check network activity and health. -It is designed for validators and testing protocol changes. You will most likely not develop on the Baklava testnet. If you have an idea for a project that uses more protocol features in terms of handling the community fund or uniquely handling epoch rewards, like block rewards or staking rewards, it might be useful to develop on Baklava. + -* [Baklava Faucet Request Form](https://forms.gle/JTYkMAJWTAUQp1sv9) - to request faucetted funds to become a Validator on the Baklava network. -* [Baklava Network Status](https://baklava-celostats.celo-testnet.org/) - to check the current availability of the testnet -* [Baklava Network Block Explorer](https://baklava-blockscout.celo-testnet.org/) - explore the history of the blockchain and view transaction details +## Hosted Nodes -### Hosted Node Service (Forno) +### Forno [Forno](../developer-guide/forno) is a cLabs hosted node service for interacting with the Celo network. This allows you to connect to the Celo Blockchain without having to run your own node. @@ -108,78 +99,22 @@ Forno has HTTP and WebSocket endpoints that you can use to query current Celo da Forno can be used as an HTTP Provider with ContractKit. + + ### Figment Datahub [Figment datahub](https://figment.io/datahub/celo/) is a service similar to Forno. They have some additional features that allow you to track how people are using your application in terms of the type and number of requests coming through the endpoints. They have a free tier with the option to pay for the service to increase limits to support more popular projects. + + ### Quicknode [Quicknode](https://www.quicknode.com/chains/celo) is an enterprise grade node service with a dashboard, metrics, security controls, customer support and no rate limits (pay-as-you-go). + + ## Celo Wallets [Celo Wallets](../getting-started/wallets) are tools that create accounts, manage keys, and help users transact on the Celo network. -The Celo Wallet is an easy way to send, receive, and save Celo assets. This section describes what is going on under the hood during various aspects of the wallet experience. - -It's important to be careful when choosing a wallet because they manage your secret account keys. You should only use reputable wallets that are well maintained by organizations/people that you trust. - -The Celo Native Wallets section shows some popular wallets that were built specifically for the Celo network. They often include features that more general wallets do not, like paying for fees with cUSD. The Celo Compatible Wallets section has wallets that can work with Celo but were built for other networks (like Ethereum) or through company partnerships (like Pesabase). - -## Smart Contracts - -A smart contract is a deterministic program running on a blockchain. The terms of the agreement (the program) are written as lines of code. The code and the agreements contained therein exist across a distributed, decentralized blockchain network. The code controls the execution, and transactions are trackable and irreversible. - -Celo includes both protocol contracts and application-specific contracts. - -Smart contracts running on Celo are functionally (and often programatically) identitcal to [smart contracts running on Ethereum](https://ethereum.org/en/developers/docs/smart-contracts/#top). - -### Protocol Contracts - -Protocol contracts exist at the lowest layer and include functionality like the Celo election process and code that runs the Celo proof of stake system and on-chain governance. - -### Application Contracts - -Application contracts may or may not be built by cLabs. These contracts are custom-built by developers to support application functionality. - -### Ethereum Contracts - -[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts) has a common token, governance, access control, utility contracts written in Solidity. - -## Infrastructure - -### BlockScout - -[BlockScout](https://explorer.celo.org/) is a cLabs hosted GUI block explorer and [API endpoints](https://explorer.celo.org/api_docs). It allows you to look up information about the Celo blockchain including average block time, total transactions, and additional transaction details. You may also view details of your own custom smart contracts or existing DeFi contracts to view how value is moving between accounts and on-chain network events. - -The [API endpoints](https://explorer.celo.org/api_docs) allow you programmatically fetch blockchain data such as account balances and transaction history, smart contract interactions and events (logs), and block and transaction-specific information. - -### ODIS - -- [ODIS](/developer-resources/contractkit/odis.md) - - Oblivious decentralized identity service - - Lightweight identity layer that makes it easy to send cryptocurrency to a phone number -- Blockscout block explorers - -### The Graph - -[The Graph](https://thegraph.com/) is an indexing protocol for querying networks like Celo, Ethereum and IPFS. Anyone can build and publish open APIs, called subgraphs, making data easily accessible. Many blockchain data querying tools like Dapplooker leverage the Graph. You can read more about how to use the Graph with Celo [here](/blog/using-the-graph). - -### DappLooker - -[DappLooker](https://dapplooker.com/integration/celo) allows you to easily analyze & visualize your Celo smart contracts & subgraph data in various formats and gather it into dashboards from multiple sources. Analyze your data with intuitive Visual SQL which writes queries for you. Share the story your data tells with your team or with your community. Share dashboard insights via URL wherever you need to make your organization truly data driven. - -### Stats.celo.org - -- [Stats.celo.org](http://stats.celo.org) allows you to check network activity and health. - -### Ongoing projects - -- [Wallets](../getting-started/wallets/index.md) -- [Community projects & Ecosystem](https://celohub.org/) -- [Grant recipients](https://celo.org/experience/grants/directory) - -### Community - -- Join our [Discord](https://chat.celo.org) -- [Discourse Forum](https://forum.celo.org/) + diff --git a/docs/learn/introduction-to-celo.md b/docs/learn/key-concepts.md similarity index 88% rename from docs/learn/introduction-to-celo.md rename to docs/learn/key-concepts.md index eeb958a640..1c35941170 100644 --- a/docs/learn/introduction-to-celo.md +++ b/docs/learn/key-concepts.md @@ -1,7 +1,7 @@ --- -title: Introduction to Celo -id: introduction-to-celo -slug: /introduction-to-celo +title: Key Concepts +id: key-concepts +slug: /key-concepts description: Celo believes in a future where everyone can prosper. --- @@ -19,20 +19,14 @@ With its interoperability, cross-chain compatibility and vision for inclusivity, -[View Celo DApps](/developer-guide/celo-dapp-gallery) - ## What is CELO? CELO is a platform-native reserve and governance asset, serving as the primary asset in the stability mechanism (Mento) that supports stable digital currencies like cUSD and cEUR. CELO’s primary function is stabilization, ensuring the healthy velocity of assets that globally circulate and transact on Celo. CELO also serves as the key governance mechanism for the Celo Platform. Owning and using CELO supports the growth and development of the Celo Platform by enabling each CELO owner to vote on proposals that direct how the core technology operates today and in the future. -[Learn more about Celo](/why-celo) - ## What can Celo Dollars Do? Named for the currencies they follow, Celo Dollars (cUSD) and Celo Euros (cEUR) are stablecoins that allow you to share value faster, cheaper, and more easily on your mobile phone. Celo stablecoins instantly unlock access for everyday uses like low-cost remittances and cross-border payments, global distribution of charitable aid, effortlessly paying online, or transferring value within exchanges, particularly in markets subject to currency volatility. - -[Get a Celo Wallet](../getting-started/wallets) diff --git a/docs/learn/walletconnect.md b/docs/learn/walletconnect.md new file mode 100644 index 0000000000..43f0a7672d --- /dev/null +++ b/docs/learn/walletconnect.md @@ -0,0 +1,7 @@ +--- +title: WalletConnect +--- + +# WalletConnect + +[WalletConnect](https://walletconnect.com/) is a standard across EVM compatible blockchains to connect wallets to dapps. It allows developers to build connections between wallets and dapps on the same desktop or mobile device, or between desktop dapps and mobile wallets. diff --git a/docs/welcome.md b/docs/welcome.md index d754f22143..6bd027da3b 100644 --- a/docs/welcome.md +++ b/docs/welcome.md @@ -2,7 +2,7 @@ title: Welcome to Celo description: Celo's mission is to build a financial system that creates the conditions for prosperity—for everyone. id: welcome -slug: /welcome +slug: / --- import YouTube from '@components/YouTube'; @@ -16,7 +16,11 @@ Celo's mission is to build a financial system that creates the conditions for pr Celo is a mobile-first blockchain that makes decentralized financial (DeFi) tools and services accessible to anyone with a mobile phone. It aims to break down barriers by bringing the powerful benefits of DeFi to the users of the 6 billion smartphones in circulation today. -[View Website](https://www.celo.org) +:::tip + +First time visiting Celo? [View the Website](https://www.celo.org) + +::: ## Celo's Mission @@ -33,5 +37,3 @@ An Ethereum-compatible technology capable of reaching global users at scale, Cel ## Get started with Celo To build technology and products that are used and loved by people and solve real-world problems, Celo is building a community with many different perspectives and experiences. Let’s build a monetary system that creates the conditions for prosperity for all. - - diff --git a/docusaurus.config.js b/docusaurus.config.js index 7146f7d7ca..e664d1db2f 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -318,19 +318,14 @@ module.exports = { src: "img/color-logo.png", }, items: [ - { - "to": "welcome", - "label": "Basics", - "position": "left" - }, - { - "to": "celo-holder-guide/overview", - "label": "Use Celo", - "position": "left" - }, + // { + // "to": "welcome", + // "label": "Basics", + // "position": "left" + // }, { "to": "developer-guide/overview", - "label": "Develop", + "label": "Build", "position": "left" }, { @@ -345,7 +340,7 @@ module.exports = { }, { "to": "/blog", - "label": "Tutorials", + "label": "Learn", "position": "left" }, { diff --git a/sidebars.js b/sidebars.js index 39f05e5c2b..ec1de02259 100644 --- a/sidebars.js +++ b/sidebars.js @@ -1,73 +1,22 @@ const sidebars = { docs: [ { type: 'doc', label: 'Welcome to Celo', id: 'welcome', }, - { type: 'doc', label: 'Key Concepts', id: 'learn/introduction-to-celo', }, - { type: 'doc', label: 'Architecture', id: 'learn/celo-stack', }, - { type: 'doc', label: 'Whitepapers', id: 'learn/celo-whitepapers', }, - { type: 'doc', label: 'Community', id: 'community/join-the-community', }, - { type: "doc", label: "Glossary", id: "getting-started/glossary",}, - { type: "doc", label: "Gallery", id: "developer-resources/celo-dapp-gallery",}, - { type: 'doc', label: 'FAQ', id: 'faqs', }, - // { - // type: "category", - // label: "Getting Started", - // items: [ - // { - // type: 'category', - // label: 'Celo Basics', - // items: [ - // { type: 'doc', label: 'Why Celo', id: 'learn/why-celo', }, - // { type: 'doc', label: 'Highlights', id: 'learn/celo-highlights', }, - // { type: 'doc', label: 'Economic Model', id: 'learn/celo-economic-model', }, - // { type: 'doc', label: 'Milestones', id: 'learn/celo-milestones', }, - // { type: 'doc', label: 'Ecosystem', id: 'learn/celo-ecosystem', }, - // ] - // }, - // { - // type: 'category', - // label: 'Celo Platform', - // items: [ - // { type: 'doc', label: 'Introduction', id: 'overview', }, - // { type: 'doc', label: 'Network Topology', id: 'learn/topology-of-a-celo-network', }, - // { type: 'doc', label: 'Celo Protocol', id: 'learn/celo-protocol', }, - // ] - // }, - // ], - // }, - ], - - // ###################################### - // validators - // ###################################### - validators: [ - { type: "doc", label: "Overview", id: "validator-guide/overview",}, - { type: "doc", label: "Attestation Service", id: 'validator-guide/attestation-service',}, - { - type: 'category', - label: 'Key Management', - items: [ - { type: "doc", label: "Summary", id: 'validator-guide/key-management/summary',}, - { type: "doc", label: "Key Management", id: 'validator-guide/key-management/detailed',}, - { type: "doc", label: "Key Rotation", id: 'validator-guide/key-management/key-rotation',}, - ] - }, - { type: 'doc', label: 'Run Secure Nodes and Services', id: 'validator-guide/securing-nodes-and-services', }, - { type: 'doc', label: 'Monitoring', id: 'validator-guide/monitoring', }, - { type: 'doc', label: 'DevOps Best Practices', id: 'validator-guide/devops-best-practices', }, - { type: 'doc', label: 'Node Upgrades', id: 'validator-guide/node-upgrades', }, - { type: 'doc', label: 'Running Proxies', id: 'validator-guide/proxy', }, - { type: 'doc', label: 'Validator Explorer', id: 'validator-guide/validator-explorer', }, - { type: 'doc', label: 'Voting Policy', id: 'validator-guide/celo-foundation-voting-policy',}, - { type: 'doc', label: 'Celo Signal', id: 'validator-guide/celo-signal',}, - { type: "doc", label: "Validator FAQ", id: "getting-started/validator-troubleshooting-faq",}, - ], - - // ###################################### - // users - // ###################################### - - users: [ - { type: 'doc', label: 'Overview', id: 'celo-holder-guide/overview' }, + { + type: "category", + label: "Basics", + items: [ + { type: 'doc', label: 'Why Celo', id: 'learn/why-celo', }, + { type: 'doc', label: 'Highlights', id: 'learn/celo-highlights', }, + { type: 'doc', label: 'Economic Model', id: 'learn/celo-economic-model', }, + { type: 'doc', label: 'Milestones', id: 'learn/celo-milestones', }, + { type: 'doc', label: 'Ecosystem', id: 'learn/celo-ecosystem', }, + { type: 'doc', label: 'Key Concepts', id: 'learn/key-concepts', }, + { type: 'doc', label: 'Architecture', id: 'learn/celo-stack', }, + { type: 'doc', label: 'Whitepapers', id: 'learn/celo-whitepapers', }, + { type: 'doc', label: 'Community', id: 'community/join-the-community', }, + { type: "doc", label: "Glossary", id: "getting-started/glossary",}, + ] + }, { type: "category", label: "Wallets", @@ -276,99 +225,161 @@ const sidebars = { { type: 'doc', label: 'Hosted Nodes', id: "getting-started/hosted-nodes", }, ], }, - { - type: "category", - label: "Command Line", - items: [ + { type: "doc", label: "Gallery", id: "developer-resources/celo-dapp-gallery",}, + { type: 'doc', label: 'FAQ', id: 'faqs', }, + // { + // type: 'category', + // label: 'Celo Platform', + // items: [ + // { type: 'doc', label: 'Introduction', id: 'overview', }, + // { type: 'doc', label: 'Network Topology', id: 'learn/topology-of-a-celo-network', }, + // { type: 'doc', label: 'Celo Protocol', id: 'learn/celo-protocol', }, + // ] + // }, { - type: "autogenerated", - dirName: "command-line-interface", + type: "category", + label: "Command Line", + items: [ + { + type: "autogenerated", + dirName: "command-line-interface", + }, + ], }, - ], - }, + ], + + // ###################################### + // validators + // ###################################### + validators: [ + { type: "doc", label: "Overview", id: "validator-guide/overview",}, + { type: "doc", label: "Attestation Service", id: 'validator-guide/attestation-service',}, + { + type: 'category', + label: 'Key Management', + items: [ + { type: "doc", label: "Summary", id: 'validator-guide/key-management/summary',}, + { type: "doc", label: "Key Management", id: 'validator-guide/key-management/detailed',}, + { type: "doc", label: "Key Rotation", id: 'validator-guide/key-management/key-rotation',}, + ] + }, + { type: 'doc', label: 'Run Secure Nodes and Services', id: 'validator-guide/securing-nodes-and-services', }, + { type: 'doc', label: 'Monitoring', id: 'validator-guide/monitoring', }, + { type: 'doc', label: 'DevOps Best Practices', id: 'validator-guide/devops-best-practices', }, + { type: 'doc', label: 'Node Upgrades', id: 'validator-guide/node-upgrades', }, + { type: 'doc', label: 'Running Proxies', id: 'validator-guide/proxy', }, + { type: 'doc', label: 'Validator Explorer', id: 'validator-guide/validator-explorer', }, + { type: 'doc', label: 'Voting Policy', id: 'validator-guide/celo-foundation-voting-policy',}, + { type: 'doc', label: 'Celo Signal', id: 'validator-guide/celo-signal',}, + { type: "doc", label: "Validator FAQ", id: "getting-started/validator-troubleshooting-faq",}, ], + // ###################################### // Developers // ###################################### + developers: [ { type: 'doc', label: 'Overview', id: 'developer-resources/overview', }, - // { type: 'doc', label: 'Basics', id: 'developer-resources/developer-basics',}, { type: 'category', - label: 'Local Environment', + label: 'Installation', items: [ - { type: 'doc', label: 'Start Building', id: 'developer-resources/deploy-dapp',}, - 'developer-resources/deploy-remix', - 'developer-resources/deploy-truffle', - 'developer-resources/deploy-hardhat', - 'developer-resources/deploy-replit', + { type: 'doc', label: 'Using Mac', id: 'developer-resources/using-mac',}, + { type: 'doc', label: 'Using Windows', id: 'developer-resources/develop-on-windows',}, ] - }, + }, { - type: "category", - label: "Developer Tools", + type: 'category', + label: 'Wallet', items: [ - { type: 'doc', label: 'Overview', id: 'learn/developer-tools', }, - { type: 'doc', label: 'EVM Tools', id: 'learn/evm-compatible-tooling', }, + { type: 'doc', label: 'MetaMask', id: 'developer-resources/testnet-wallet', }, { type: 'category', - label: 'ContractKit', + label: 'Celo Wallet', items: [ - { type: 'doc', label: 'Overview', id: 'developer-resources/contractkit/index',}, - { type: 'doc', label: 'Setup', id: 'developer-resources/contractkit/setup',}, - { type: 'doc', label: 'Usage', id: 'developer-resources/contractkit/usage',}, - { type: 'doc', label: 'Use Web3 from ContracKit', id: 'developer-resources/contractkit/notes-web3-with-contractkit',}, - { type: 'doc', label: 'Wrappers & Registry Contracts', id: 'developer-resources/contractkit/contracts-wrappers-registry',}, - { type: 'doc', label: 'Query On-Chain Identifiers with ODIS', id: 'developer-resources/contractkit/odis',}, - { type: 'doc', label: 'Migrate to ContractKit v1', id: 'developer-resources/contractkit/migrating-to-contractkit-v1',}, + { type: 'doc', label: 'Celo Wallet', id: 'celo-codebase/wallet/index', }, + { type: 'doc', label: 'Running the wallet locally', id: 'celo-codebase/wallet/intro', }, + { type: "doc", label: "Using the Wallet", id: "getting-started/using-the-wallet",}, ] }, + { type: 'link', label: 'Faucet', href: 'https://celo.org/developers/faucet',}, + ], + }, + { + type: "category", + label: "Tools", + items: [ + { type: 'doc', label: 'Overview', id: 'learn/developer-tools', }, { type: 'category', - label: 'DAppKit', + label: 'SDKs', items: [ - { type: 'doc', label: 'Overview', id: 'developer-resources/dappkit/index',}, - { type: 'doc', label: 'Setup', id: 'developer-resources/dappkit/setup',}, - { type: 'doc', label: 'Usage', id: 'developer-resources/dappkit/usage',}, - ] - }, - { type: 'doc', label: 'Forno', id: 'developer-resources/forno/index',}, - { type: 'doc', label: 'Wallet', id: 'developer-resources/testnet-wallet', }, + { + type: 'category', + label: 'ContractKit', + items: [ + { type: 'doc', label: 'Overview', id: 'developer-resources/contractkit/index',}, + { type: 'doc', label: 'Setup', id: 'developer-resources/contractkit/setup',}, + { type: 'doc', label: 'Usage', id: 'developer-resources/contractkit/usage',}, + { type: 'doc', label: 'Use Web3 from ContracKit', id: 'developer-resources/contractkit/notes-web3-with-contractkit',}, + { type: 'doc', label: 'Wrappers & Registry Contracts', id: 'developer-resources/contractkit/contracts-wrappers-registry',}, + { type: 'doc', label: 'Query On-Chain Identifiers with ODIS', id: 'developer-resources/contractkit/odis',}, + { type: 'doc', label: 'Migrate to ContractKit v1', id: 'developer-resources/contractkit/migrating-to-contractkit-v1',}, + ] + }, + { type: 'doc', label: 'use-contractkit', id: 'developer-resources/use-contractkit', }, + { type: 'doc', label: 'Ethers.JS Wrapper', id: 'developer-resources/ethers-js-wrapper', }, + { type: 'doc', label: 'WalletConnect', id: 'learn/walletconnect', }, + { + type: 'category', + label: 'DAppKit', + items: [ + { type: 'doc', label: 'Overview', id: 'developer-resources/dappkit/index',}, + { type: 'doc', label: 'Setup', id: 'developer-resources/dappkit/setup',}, + { type: 'doc', label: 'Usage', id: 'developer-resources/dappkit/usage',}, + ] + }, + { type: 'link', label: 'Command Line', href: 'https://docs.celo.org/command-line-interface/introduction',}, + ], + }, + { + type: 'category', + label: 'Infrastructure', + items: [ + { type: 'link', label: 'BlockScout', href: 'https://explorer.celo.org/',}, + { type: 'link', label: 'ODIS', href: 'https://docs.celo.org/command-line-interface/introduction',}, + { type: 'link', label: 'The Graph', href: 'https://thegraph.com/en/',}, + { type: 'link', label: 'DappLooker', href: 'https://dapplooker.com/integration/celo',}, + { type: 'link', label: 'stats.celo.org', href: 'https://stats.celo.org/',} + ], + }, + { + type: 'category', + label: 'Hosted Nodes', + items: [ + { type: 'doc', label: 'Forno', id: 'developer-resources/forno/index',}, + ], + }, { type: 'doc', label: 'Development Chain', id: 'developer-resources/walkthroughs/development-chain', }, + { type: 'doc', label: 'Ethereum Tools', id: 'learn/evm-compatible-tooling', }, ], }, { type: 'category', - label: 'Code Examples', - items: [ - { type: 'doc', label: 'Introduction', id: 'developer-resources/start',}, - { type: 'doc', label: 'Sending CELO & Stable Assets', id: 'developer-resources/walkthroughs/hellocelo',}, - { type: 'doc', label: 'Deploy to a Local Node', id: 'developer-resources/walkthroughs/hellocontracts',}, - { type: 'doc', label: 'Deploy to a Remote Node', id: 'developer-resources/walkthroughs/hello-contract-remote-node',}, - 'developer-resources/walkthroughs/no-code-erc20', - 'developer-resources/walkthroughs/no-code-erc721', - 'developer-resources/walkthroughs/web-dapp', - { type: 'doc', label: 'Use onchain randomness', id: 'developer-resources/walkthroughs/randomness',}, - { type: 'doc', label: 'Valora + Wallet Connect', id: 'developer-resources/walkthroughs/valora-wc-v1',}, - { type: 'doc', label: 'Using Keystores', id: 'developer-resources/walkthroughs/using-js-keystores',}, - { type: 'link', label: 'Figment | Celo 101', href: 'https://learn.figment.io/protocols/celo/' }, - { type: 'link', label: 'Dacade | Celo 101', href: 'https://dacade.org/communities/celo-development-101' }, - ] - }, - { - type: 'category', - label: 'Build on Mobile', + label: 'Deploy', items: [ - { type: 'doc', label: 'Celo Wallet', id: 'celo-codebase/wallet/index', }, - { type: 'doc', label: 'Running the wallet locally', id: 'celo-codebase/wallet/intro', }, - { type: "doc", label: "Using the Wallet", id: "getting-started/using-the-wallet",}, + { type: 'doc', label: 'Overview', id: 'developer-resources/deploy-dapp',}, + { type: 'doc', label: 'Remix', id: 'developer-resources/deploy-remix', }, + { type: 'doc', label: 'Truffle', id: 'developer-resources/deploy-truffle', }, + { type: 'doc', label: 'Hardhat', id: 'developer-resources/deploy-hardhat', }, + { type: 'doc', label: 'Replit', id: 'developer-resources/deploy-replit' }, ] }, { type: 'category', - label: 'Integrate with Celo', + label: 'Integrate', items: [ - { type: 'doc', label: 'Integrations', id: 'developer-resources/integrations/integrations' }, + { type: 'doc', label: 'Overview', id: 'developer-resources/integrations/integrations' }, { type: 'doc', label: 'General', id: 'developer-resources/integrations/general' }, { type: 'doc', label: 'Checklist', id: 'developer-resources/integrations/checklist' }, { type: 'doc', label: 'Custody', id: 'developer-resources/integrations/custody' }, @@ -376,6 +387,25 @@ const sidebars = { { type: 'doc', label: 'Cloud HSM', id: 'developer-resources/integrations/cloud-hsm' }, ], }, + { + type: 'category', + label: 'Tutorials', + items: [ + // { type: 'doc', label: 'Introduction', id: 'developer-resources/start',}, + // { type: 'doc', label: 'Sending CELO & Stable Assets', id: 'developer-resources/walkthroughs/hellocelo',}, + // { type: 'doc', label: 'Deploy to a Local Node', id: 'developer-resources/walkthroughs/hellocontracts',}, + // { type: 'doc', label: 'Deploy to a Remote Node', id: 'developer-resources/walkthroughs/hello-contract-remote-node',}, + // 'developer-resources/walkthroughs/no-code-erc20', + // 'developer-resources/walkthroughs/no-code-erc721', + // 'developer-resources/walkthroughs/web-dapp', + // { type: 'doc', label: 'Use onchain randomness', id: 'developer-resources/walkthroughs/randomness',}, + // { type: 'doc', label: 'Valora + Wallet Connect', id: 'developer-resources/walkthroughs/valora-wc-v1',}, + // { type: 'doc', label: 'Using Keystores', id: 'developer-resources/walkthroughs/using-js-keystores',}, + { type: 'link', label: 'Celo Tutorials', href: 'https://docs.celo.org/blog', }, + { type: 'link', label: 'Figment | Celo 101', href: 'https://learn.figment.io/protocols/celo/' }, + { type: 'link', label: 'Dacade | Celo 101', href: 'https://dacade.org/communities/celo-development-101' }, + ] + }, { type: 'category', label: 'From another platform?', @@ -429,8 +459,8 @@ const sidebars = { type: 'category', label: 'Resources', items: [ - { type: 'doc', label: 'Celo Onboarding', id: 'learn/celo-onboarding', }, - { type: 'doc', label: 'Developer Onboarding', id: 'learn/developer-onboarding', }, + // { type: 'doc', label: 'Celo Onboarding', id: 'learn/celo-onboarding', }, + // { type: 'doc', label: 'Developer Onboarding', id: 'learn/developer-onboarding', }, { type: 'category', label: 'Quick Guides', @@ -442,7 +472,7 @@ const sidebars = { { type: 'doc', label: 'Celo Stablecoins', id: 'learn/platform-native-stablecoins-summary', }, ] }, - { type: 'doc', label: 'Figment Learn', id: 'learn/figment-learn', }, + // { type: 'doc', label: 'Figment Learn', id: 'learn/figment-learn', }, { type: 'doc', label: 'Celo Resources', id: 'learn/celo-resources', }, ] }, diff --git a/src/components/HomepageFeatures.js b/src/components/HomepageFeatures.js index e90f6bf72b..ebbad028cd 100644 --- a/src/components/HomepageFeatures.js +++ b/src/components/HomepageFeatures.js @@ -14,23 +14,13 @@ const FeatureList = [ ), }, { - title: 'Use Celo', - // Svg: require('../../static/img/homepage/1.svg').default, - description: ( - <>Start sending, spending, and earning crypto from your mobile phone. - ), - link: ( - Use the Celo network - ), - }, - { - title: 'Become a developer', + title: 'Build on Celo', // Svg: require('../../static/img/homepage/1.svg').default, description: ( <>Build, deploy, and manage applications on the Celo network. ), link: ( - Build on Celo + Start building ), }, { @@ -44,17 +34,17 @@ const FeatureList = [ ), }, { - title: 'Join the community', + title: 'Contribute to Celo', // Svg: require('../../static/img/homepage/1.svg').default, description: ( - <>Join a community of developers, designers, dreamers, and doers. + <>Start sending, spending, and earning crypto from your mobile phone. ), link: ( - Contribute to Celo + Use the Celo network ), }, { - title: 'Find more tutorials', + title: 'Learn by coding', // Svg: require('../../static/img/homepage/1.svg').default, description: ( <>Gain the skills you need to get the most from the Celo platform. @@ -64,6 +54,16 @@ const FeatureList = [ Learn more with Celo ), }, + { + title: 'Join the Discussion', + // Svg: require('../../static/img/homepage/1.svg').default, + description: ( + <>Join a community of developers, designers, dreamers, and doers. + ), + link: ( + Join Discord + ), + }, ]; function Feature({title, description, link}) { diff --git a/src/pages/index.js b/src/pages/remove-index.js similarity index 97% rename from src/pages/index.js rename to src/pages/remove-index.js index 7eaa15b6f5..a67d893a93 100644 --- a/src/pages/index.js +++ b/src/pages/remove-index.js @@ -16,7 +16,7 @@ function HomepageHeader() {
+ to="/"> Get Started
@@ -37,4 +37,4 @@ export default function Home() { ); -} \ No newline at end of file +}