diff --git a/src/content/docs/developer/duskevm/quickstart.md b/src/content/docs/developer/duskevm/quickstart.md index 0d64cf3d..aee97e31 100644 --- a/src/content/docs/developer/duskevm/quickstart.md +++ b/src/content/docs/developer/duskevm/quickstart.md @@ -5,6 +5,8 @@ description: Fund a testnet account and deploy a Solidity contract to DuskEVM. Deploy a Solidity contract to DuskEVM Testnet with Foundry or Hardhat. DuskEVM uses the standard Ethereum JSON-RPC interface, so the workflow is the same one used for other OP Stack networks. +Install either [Foundry](https://getfoundry.sh/) or [Node.js](https://nodejs.org/) for the Hardhat path. Use a dedicated deployment account rather than a wallet that holds production funds. + ## Testnet | Setting | Value | @@ -22,6 +24,8 @@ cast chain-id --rpc-url https://rpc.testnet.evm.dusk.network # 745 ``` +Do not continue if the RPC is unavailable or returns a different chain ID. + ## 1. Fund the deployer Create a dedicated EVM deployment account, then [bridge testnet DUSK to it](/learn/guides/duskevm-bridge/). Keep enough DUSK in the account to pay deployment gas. @@ -51,7 +55,13 @@ forge create src/Counter.sol:Counter \ ### Hardhat 3 -Initialize a Hardhat project with the viem toolbox, then add DuskEVM Testnet to `hardhat.config.ts`: +Initialize a Hardhat project: + +```bash +npx hardhat --init +``` + +Choose **Hardhat 3** and the **TypeScript project using Node Test Runner and Viem**. Then replace the generated network configuration with DuskEVM Testnet in `hardhat.config.ts`: ```ts title="hardhat.config.ts" import hardhatToolboxViemPlugin from "@nomicfoundation/hardhat-toolbox-viem"; diff --git a/src/content/docs/developer/duskvm/overview.md b/src/content/docs/developer/duskvm/overview.md index 84c363bb..84336972 100644 --- a/src/content/docs/developer/duskvm/overview.md +++ b/src/content/docs/developer/duskvm/overview.md @@ -21,6 +21,7 @@ Both environments are general-purpose. DuskVM executes contracts directly on the | Component | Role | |---|---| | [Forge](https://github.com/dusk-network/forge) | Scaffolds contracts and generates ABI exports, schemas, and data drivers from annotated Rust | +| [Dusk contract standards](https://github.com/dusk-network/contracts/tree/main/standards) | Provides reusable Dusk-native contract primitives and reference implementations | | [DuskVM](/learn/deep-dive/dusk-vm/) | Executes contract WASM and persists contract state | | [Rusk Wallet](/use/wallets/#rusk-wallet) | Signs and submits deployment and contract-call transactions | | [Dusk Connect](/developer/integrations/dusk-connect/) | Connects browser dApps to compatible Dusk wallet extensions for account access and transaction approval | @@ -28,9 +29,20 @@ Both environments are general-purpose. DuskVM executes contracts directly on the A typical workflow is: -1. Scaffold a contract with Forge. +1. Start from a reusable standards primitive where one fits, then scaffold the contract with Forge. 2. Implement and test it locally against DuskVM. 3. Build and verify the contract and data-driver WASM artifacts. 4. Deploy the contract, then connect applications through Dusk Connect, W3sper, or the HTTP API. +## Start from the standards + +The [Dusk contract standards workspace](https://github.com/dusk-network/contracts/tree/main/standards) provides composable Rust building blocks for recurring contract concerns: + +- **Tokens:** DRC20 balances, allowances, events, supply caps, checkpoints, and voting units +- **Access and security:** ownership, owner sets, roles, pausing, and reentrancy protection +- **Authorization and governance:** Dusk principals, nonce and replay protection, threshold multisig, and a multisig controller +- **Reference contracts:** a role-controlled pausable DRC20, multisig controller, and Moonlight call router + +The implementations, tests, events, and examples provide a common Dusk-native base instead of requiring each project to recreate these patterns. Pin the repository revision used by your contract so builds remain reproducible as the standards evolve. + Start with the [DuskVM quickstart](/developer/duskvm/quickstart/). Use the [contract reference](/developer/duskvm/reference/) when you need the ABI, state, serialization, event, or deployment details. diff --git a/src/content/docs/developer/duskvm/quickstart.md b/src/content/docs/developer/duskvm/quickstart.md index 3b2254d5..208d1dfe 100644 --- a/src/content/docs/developer/duskvm/quickstart.md +++ b/src/content/docs/developer/duskvm/quickstart.md @@ -80,7 +80,7 @@ Keep the `0x` prefix when an SDK expects prefixed hex. Remove it for `rusk-walle ## 5. Deploy on testnet -Install and configure [Rusk Wallet](/use/wallets/#rusk-wallet) and make sure a public account has enough testnet DUSK for deployment. [Request funds from the testnet faucet](/operator/networks/#how-to-get-testnet-tokens) if needed. The commands below target testnet explicitly and use the wallet's first address by default; add `--address
` to use another funded address. Testnet DUSK has no monetary value. +Install [Rusk Wallet 0.3.0 or later](https://github.com/dusk-network/rusk/releases?q=rusk+wallet&expanded=true), configure it for testnet, and make sure a public account has enough testnet DUSK for deployment. [Request funds from the testnet faucet](/operator/networks/#how-to-get-testnet-tokens) if needed. The commands below target testnet explicitly and use the wallet's first address by default; add `--address
` to use another funded address. Testnet DUSK has no monetary value. Deploy the on-chain artifact with a nonce you have not used for the same contract and account: @@ -90,7 +90,7 @@ rusk-wallet --network testnet contract-deploy \ --deploy-nonce ``` -The wallet prints the contract ID and waits for the deployment transaction to be included. Keep the contract ID for later calls. +The wallet first prints `Deploying `, waits for inclusion, and then prints the deployment transaction hash. Keep the contract ID from the first line for later calls. Call an entrypoint with no arguments by passing an empty hex value: diff --git a/src/content/docs/developer/integrations/w3sper.md b/src/content/docs/developer/integrations/w3sper.md index 429e2bad..df21a5ab 100644 --- a/src/content/docs/developer/integrations/w3sper.md +++ b/src/content/docs/developer/integrations/w3sper.md @@ -1,9 +1,11 @@ --- title: W3sper SDK -description: JavaScript SDK for generating profiles, building transactions, and querying Dusk nodes. +description: Query Rusk nodes and use lower-level Dusk profile, synchronization, and transaction primitives from JavaScript. --- -W3sper (`@dusk/w3sper`) is the JavaScript SDK used by Dusk apps and tooling to interact with nodes. Prefer it over calling raw RUES endpoints directly from application code. +W3sper (`@dusk/w3sper`) is the JavaScript client for direct access to Rusk nodes. It covers node queries, account and shielded-state synchronization, data-driver based contract reads, and the lower-level primitives used by applications that manage their own wallet state. + +Use [Dusk Connect](/developer/integrations/dusk-connect/) instead when a browser dApp should discover a wallet extension and ask the user to approve access or transactions. Use the [HTTP API and RUES reference](/developer/integrations/http-api/) for raw or non-JavaScript integrations. ## Install @@ -11,62 +13,48 @@ W3sper (`@dusk/w3sper`) is the JavaScript SDK used by Dusk apps and tooling to i deno add jsr:@dusk/w3sper ``` -## Connect +## Connect and query + +`Network.connect()` opens the RUES connection and loads the protocol driver required by profile and transaction APIs. ```js import { Network } from "@dusk/w3sper"; const network = await Network.connect("https://testnet.nodes.dusk.network"); -console.log(await network.node.info); -``` - -## Generate a Profile - -A seeder is an (async) function that returns a `Uint8Array` (64 bytes). - -```js -import { ProfileGenerator } from "@dusk/w3sper"; - -const seeder = () => crypto.getRandomValues(new Uint8Array(64)); -const profiles = new ProfileGenerator(seeder); - -const me = await profiles.default; - -// Moonlight (public) account (Base58, 96 bytes) -console.log(me.account.toString()); - -// Phoenix (shielded) address (Base58, 64 bytes) -console.log(me.address.toString()); -``` -## Get a Balance (Moonlight) +try { + const info = await network.node.info; + const height = await network.blockHeight; -```js -import { AccountSyncer } from "@dusk/w3sper"; - -const [balance] = await new AccountSyncer(network).balances([me]); -console.log(balance); // { nonce: bigint, value: bigint } (value in LUX) + console.log({ version: info.version, chain: String(info.chain), height }); +} finally { + await network.disconnect(); +} ``` -## Send a Transfer (Moonlight) +## Read a public balance -Amounts are in `LUX` (`1 DUSK = 1_000_000_000 LUX`). +`AccountSyncer` accepts a Moonlight account string; reading a balance does not require its private key. ```js -import { Transfer } from "@dusk/w3sper"; - -const to = ""; -const txBuilder = new Transfer(me).amount(1_000_000_000n).to(to); +import { AccountSyncer, Network, lux } from "@dusk/w3sper"; -const { hash } = await network.execute(txBuilder); -await network.transactions.withId(hash).once.executed(); +const account = ""; +const network = await Network.connect("https://testnet.nodes.dusk.network"); -console.log({ hash }); +try { + const [balance] = await new AccountSyncer(network).balances([account]); + console.log(lux.formatToDusk(balance.value)); +} finally { + await network.disconnect(); +} ``` -## Query a custom contract +Balances and transaction amounts are represented in `LUX`: `1 DUSK = 1_000_000_000 LUX`. + +## Query a DuskVM contract -Forge builds a data-driver WASM artifact alongside each DuskVM contract. Serve that artifact with your application, register its URL under the deployed contract ID, and W3sper will use it to encode calls and decode results: +Forge builds a data-driver WASM artifact alongside each DuskVM contract. Serve that artifact with your application, register its URL under the deployed contract ID, and W3sper uses it to encode calls and decode results: ```js import { Contract, Network } from "@dusk/w3sper"; @@ -82,55 +70,60 @@ const counter = new Contract({ network, }); -console.log(await counter.call.get_count()); -await network.disconnect(); +try { + console.log(await counter.call.get_count()); +} finally { + await network.disconnect(); +} ``` -The driver for this example is the file produced at `target/data-driver/wasm32-unknown-unknown/release/dusk_counter.wasm`. Methods under `contract.call` are read-only; submitting contract transactions directly through W3sper also requires a synced profile and `Bookkeeper`. For browser dApps where the user's wallet should approve the transaction, use [Dusk Connect](/developer/integrations/dusk-connect/). +The driver in this example is the file produced at `target/data-driver/wasm32-unknown-unknown/release/dusk_counter.wasm` by the [DuskVM quickstart](/developer/duskvm/quickstart/). + +## Signing transactions directly + +W3sper provides transaction builders, but it does not provide a complete application wallet. A client that signs without an extension must supply recoverable key storage and a synchronized treasury behind `Bookkeeper`, including public nonces and shielded notes. + +Do not construct a transfer directly from a newly generated `Profile`: it has no synchronized `Bookkeeper` entry and the transaction cannot obtain the required balance or nonce state. For browser dApps, let Dusk Connect and the selected wallet handle signing. For a headless wallet, start from the [W3sper source and tests](https://github.com/dusk-network/rusk/tree/master/w3sper.js) and implement the storage and synchronization boundary explicitly. ## Query GraphQL -`network.query()` wraps your selection in `query { ... }` and calls the node GraphQL endpoint. +`network.query()` wraps the selection in `query { ... }` and sends it to the node GraphQL endpoint: ```js -const tip = await network.query("block(height: -1) { header { height hash } }"); -console.log(tip.block.header); -``` +const tip = await network.query( + "block(height: -1) { header { height hash } }", +); -## Offline Mode (Optional) +console.log(tip.block); +``` -When you call `Network.connect(...)`, W3sper loads the matching `wallet-core` WASM driver from the node. -For the current 1.6 line, that driver is served as `wallet-core-1.6.1.wasm`. +## Offline profile derivation -For offline usage, download that same versioned driver and load it yourself: +`Network.connect()` loads `wallet-core-1.6.1.wasm` from the selected node. An offline application can download that same driver, store it locally, and load it before using profile APIs: ```js import { ProfileGenerator, useAsProtocolDriver } from "@dusk/w3sper"; -async function getLocalWasmBuffer() { - // Must return bytes (Uint8Array/ArrayBuffer). Adjust to your environment. - return Deno.readFile("./wallet-core-1.6.1.wasm"); -} - +const driver = await Deno.readFile("./wallet-core-1.6.1.wasm"); const seeder = () => crypto.getRandomValues(new Uint8Array(64)); -await useAsProtocolDriver(await getLocalWasmBuffer()).then(async () => { - const profiles = new ProfileGenerator(seeder); - const me = await profiles.default; - console.log(me.account.toString()); -}); +await useAsProtocolDriver(driver); + +const profiles = new ProfileGenerator(seeder); +const profile = await profiles.default; +console.log(profile.account.toString()); ``` -WASM download URLs: +The random seed above is only an API demonstration. Production applications must use protected, recoverable key material and must never log or expose it. + +Driver URLs: - Mainnet: `https://nodes.dusk.network/static/drivers/wallet-core-1.6.1.wasm` - Testnet: `https://testnet.nodes.dusk.network/static/drivers/wallet-core-1.6.1.wasm` -## Units - -```js -import { lux } from "@dusk/w3sper"; +## Next steps -console.log(lux.formatToDusk(1_000_000_000n)); // "1" -console.log(lux.parseFromDusk("0.5")); // 500_000_000n -``` +- [Dusk Connect](/developer/integrations/dusk-connect/) +- [DuskVM quickstart](/developer/duskvm/quickstart/) +- [Transaction lifecycle](/developer/integrations/tx-lifecycle/) +- [HTTP API and RUES](/developer/integrations/http-api/) diff --git a/src/content/docs/developer/overview.mdx b/src/content/docs/developer/overview.mdx index a1e3eee4..b145501a 100644 --- a/src/content/docs/developer/overview.mdx +++ b/src/content/docs/developer/overview.mdx @@ -40,6 +40,15 @@ As a builder, choose the path based on what your product needs and which tooling /> +## Choose an interface + +- **EVM contract or dApp:** use standard EVM wallets, JSON-RPC, and tools such as Foundry, Hardhat, viem, or ethers. The wallet signs; DuskEVM exposes Ethereum-compatible interfaces. +- **Browser dApp on the Dusk L1:** use [Dusk Connect](/developer/integrations/dusk-connect/). The wallet extension owns the keys and asks the user to approve profile access and transactions. +- **JavaScript client that talks directly to Rusk:** use [W3sper](/developer/integrations/w3sper/). Your application owns node connectivity and, for signing, profile storage and synchronized wallet state. +- **Infrastructure, indexer, exchange, or non-JavaScript client:** use the [Rusk HTTP API and RUES](/developer/integrations/http-api/). Your integration handles raw request encoding, version headers, subscriptions, and transaction state. + +For most browser applications on the Dusk L1, use Dusk Connect. Use W3sper directly when there is no injected wallet or when you need lower-level node and wallet primitives. + ## When to use DuskEVM Use **DuskEVM** when your application is designed around the EVM ecosystem: @@ -84,5 +93,6 @@ If that’s you, start with the [DuskVM contract overview](/developer/duskvm/ove You can explore existing contracts and examples in the Dusk repos: - Protocol genesis contracts in [`contracts/genesis`](https://github.com/dusk-network/contracts/tree/main/genesis) +- Reusable DuskVM standards and reference contracts in [`contracts/standards`](https://github.com/dusk-network/contracts/tree/main/standards) - The DuskVM contract framework and template in [Forge](https://github.com/dusk-network/forge) - DuskEVM examples in the [DuskEVM quickstart](/developer/duskevm/quickstart/) diff --git a/src/sidebars/siteSidebar.js b/src/sidebars/siteSidebar.js index 8f64e8b8..ba4823ad 100644 --- a/src/sidebars/siteSidebar.js +++ b/src/sidebars/siteSidebar.js @@ -99,13 +99,13 @@ const siteSidebar = [ items: [ { label: "Dusk Connect", link: "/developer/integrations/dusk-connect" }, { label: "Dusk Wallet Integration", link: "/developer/integrations/wallet-extension" }, - { label: "W3sper SDK", link: "/developer/integrations/w3sper" }, ], }, { label: "Network Integration", collapsed: true, items: [ + { label: "W3sper SDK", link: "/developer/integrations/w3sper" }, { label: "Transaction Lifecycle", link: "/developer/integrations/tx-lifecycle" }, { label: "HTTP API", link: "/developer/integrations/http-api" }, { label: "Historical Events", link: "/developer/integrations/historical_events" },