From 8ba72e3bbf8b10231df2f3d083c153bcf1e5001c Mon Sep 17 00:00:00 2001 From: Oleksandr Myshchyshyn Date: Fri, 19 Dec 2025 14:33:38 +0200 Subject: [PATCH] updating casper js sdk documentation --- README.md | 4 +- docs/developers/dapps/sdk/script-sdk.md | 543 ++++++++++++++--- .../developers/dapps/sdk/script-sdk.md | 559 +++++++++++++++--- 3 files changed, 940 insertions(+), 166 deletions(-) diff --git a/README.md b/README.md index ba37856e5..687f3378e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Overview -This is the documentation repository for the [Casper Network](https://casper.network/). +This is the documentation repository for the [Casper Network](https://casper.network/). The documentation site itself may be viewed at this address: https://docs.casper.network/. @@ -33,7 +33,7 @@ To run the documentation site locally, follow these steps: ALGOLIA_API_KEY=your_algolia_api_key ``` - *(Note: Replace `your_algolia_app_id`, `your_algolia_index_name`, and `your_algolia_api_key` with actual values if you intend to use Algolia search; otherwise, placeholders are sufficient for local development.)* + _(Note: Replace `your_algolia_app_id`, `your_algolia_index_name`, and `your_algolia_api_key` with actual values if you intend to use Algolia search; otherwise, placeholders are sufficient for local development.)_ 3. **Install dependencies, build, and serve:** diff --git a/docs/developers/dapps/sdk/script-sdk.md b/docs/developers/dapps/sdk/script-sdk.md index f8230d92d..7c345cf20 100644 --- a/docs/developers/dapps/sdk/script-sdk.md +++ b/docs/developers/dapps/sdk/script-sdk.md @@ -1,10 +1,10 @@ # JavaScript/TypeScript SDK -This page contains details related to a few JavaScript (JS) clients and the Casper JS SDK. +This page contains details related to JavaScript (JS) clients and the Casper JS SDK. ## Usage of JavaScript Clients {#usage-of-javascript-clients} -The Casper team has implemented specific JS clients to support interaction with the Casper contracts. +The Casper team has implemented specific JS clients to support interaction with Casper contracts. ### Repository & Client Packages {#repository-7-client-packages} @@ -17,14 +17,14 @@ These packages give you an easy way to install and interact with the correspondi ## Casper SDK for JavaScript {#casper-sdk-for-javascript} -The [TypeScript/JavaScript SDK](https://github.com/casper-ecosystem/casper-js-sdk) allows developers to interact with a Casper network using TypeScript or JavaScript. This section covers different examples of using the Casper JS SDK. +The [TypeScript/JavaScript SDK](https://github.com/casper-ecosystem/casper-js-sdk) allows developers to interact with a Casper network using TypeScript or JavaScript. The SDK provides full compatibility for Casper 2.0, introducing new types, improved RPC capabilities, and support for both Transactions (Casper 2.0) and Deploys (legacy). ## Installation {#installation} To install this library using Node.js, run the following command: ```bash -npm install casper-js-sdk@next --save +npm install casper-js-sdk --save ``` ## Tests {#tests} @@ -37,137 +37,514 @@ npm run test ## Usage Examples {#usage-examples} -In this section, we outline a couple of essential tasks you can accomplish with the JavaScript SDK: +In this section, we outline essential tasks you can accomplish with the JavaScript SDK: -- Generating account keys -- Sending a transfer +- Generating account keys +- Sending a native transfer (Casper 2.0 Transaction) +- Sending a legacy deploy (backward compatibility) +- Creating CSPR, CEP-18, and NFT transfers +- Working with the RPC client +- Subscribing to SSE events ### Generating Account Keys {#generating-account-keys} -This example shows you how to use the SDK to generate account keys to sign your deploy. +This example shows you how to use the SDK to generate account keys: ```javascript -const fs = require("fs"); -const path = require("path"); -const { Keys } = require("casper-js-sdk"); +import { KeyAlgorithm, PrivateKey, PublicKey } from "casper-js-sdk"; -const createAccountKeys = () => { - // Generating keys - const edKeyPair = Keys.Ed25519.new(); - const { publicKey, privateKey } = edKeyPair; +const generateKeys = async () => { + // Choose algorithm: KeyAlgorithm.ED25519 or KeyAlgorithm.SECP256K1 + const privateKeyAlgorithm = KeyAlgorithm.ED25519; - // Create a hexadecimal representation of the public key - const accountAddress = publicKey.toHex(); + // Generate new private key + const privateKey = await PrivateKey.generate(privateKeyAlgorithm); - // Get the account hash (Uint8Array) from the public key - const accountHash = publicKey.toAccountHash(); + // Get public key from private key + const publicKey = privateKey.publicKey; - // Store keys as PEM files - const publicKeyInPem = edKeyPair.exportPublicKeyInPem(); - const privateKeyInPem = edKeyPair.exportPrivateKeyInPem(); + // Export keys as hex strings + const privateKeyHex = privateKey.toHex(); + const publicKeyHex = publicKey.toHex(); - const folder = path.join("./", "casper_keys"); + console.log("Private Key (hex):", privateKeyHex); + console.log("Public Key (hex):", publicKeyHex); - if (!fs.existsSync(folder)) { - const tempDir = fs.mkdirSync(folder); - } - - fs.writeFileSync(folder + "/" + accountAddress + "_public.pem", publicKeyInPem); - fs.writeFileSync(folder + "/" + accountAddress + "_private.pem", privateKeyInPem); + return { privateKey, publicKey }; +}; - return accountAddress; +// Recreate private key from hex string +const loadPrivateKey = async (privateKeyHex, algorithm) => { + const privateKey = await PrivateKey.fromHex(privateKeyHex, algorithm); + return privateKey; }; -const newAccountAddress = createAccountKeys(); +// Recreate public key from hex string +const loadPublicKey = (publicKeyHex) => { + const publicKey = PublicKey.fromHex(publicKeyHex); + return publicKey; +}; ``` -After generating the keys with this code, you can add them to the [Casper Wallet Chrome extension](https://www.casperwallet.io/) and use them to sign your transactions. +### Sending a Native Transfer (Casper 2.0) {#sending-a-transfer} -### Sending a Transfer {#sending-a-transfer} +This example shows how to create and send a native CSPR transfer using the Transaction API (Casper 2.0): -This code block shows you how to define and send a transfer on a Casper network. Replace the `sender-public-key` and `recipient-public-key` in the code below. +```javascript +import { + HttpHandler, + RpcClient, + NativeTransferBuilder, + PrivateKey, + KeyAlgorithm, + PublicKey, +} from "casper-js-sdk"; + +const sendNativeTransfer = async () => { + // Initialize RPC client + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + // Load or generate private key + const privateKey = await PrivateKey.generate(KeyAlgorithm.ED25519); + + // Create a native transfer transaction + const transaction = new NativeTransferBuilder() + .from(privateKey.publicKey) + .target( + PublicKey.fromHex( + "0202f5a92ab6da536e7b1a351406f3744224bec85d7acbab1497b65de48a1a707b64" + ) + ) + .amount("2500000000") // Amount in motes (2.5 CSPR) + .id(Date.now()) // Transfer ID for tracking + .chainName("casper-net-1") // Or 'casper-test' for testnet + .payment(100_000_000) // Payment amount in motes + .build(); + + // Sign the transaction + transaction.sign(privateKey); + + try { + // Submit transaction to the network + const result = await rpcClient.putTransaction(transaction); + console.log("Transaction Hash:", result.transactionHash); + + // You can check the transaction status on the block explorer: + // Testnet: https://testnet.cspr.live/transaction/ + // Mainnet: https://cspr.live/transaction/ + console.log( + `View on explorer: https://testnet.cspr.live/transaction/${result.transactionHash}` + ); + + return result.transactionHash; + } catch (error) { + console.error("Transaction failed:", error); + throw error; + } +}; +``` -The `sendTransfer` function below will return a `transfer-hash` which you can check on https://testnet.cspr.live/. +### Sending a Legacy Deploy {#sending-legacy-deploy} + +For backward compatibility with Casper 1.5, you can still create and send deploys: ```javascript -const fs = require("fs"); -const path = require("path"); -const axios = require("axios"); -const casperClientSDK = require("casper-js-sdk"); +import { + Deploy, + DeployHeader, + ExecutableDeployItem, + HttpHandler, + PublicKey, + KeyAlgorithm, + PrivateKey, + RpcClient, + TransferDeployItem, +} from "casper-js-sdk"; + +const sendLegacyDeploy = async () => { + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const senderKey = await PrivateKey.generate(KeyAlgorithm.ED25519); + const recipientKey = PublicKey.fromHex( + "010068920746ecf5870e18911EE1fC5db975E0e97fFFcBBF52f5045Ad6C9838D2F" + ); + + const paymentAmount = "10000000000000"; + const transferAmount = "10"; + const transferId = 35; + + // Create session (transfer) + const session = new ExecutableDeployItem(); + session.transfer = TransferDeployItem.newTransfer( + transferAmount, + recipientKey, + undefined, + transferId + ); + + // Create payment + const payment = ExecutableDeployItem.standardPayment(paymentAmount); + + // Create deploy header + const deployHeader = DeployHeader.default(); + deployHeader.account = senderKey.publicKey; + deployHeader.chainName = "casper-test"; + + // Make deploy + const deploy = Deploy.makeDeploy(deployHeader, payment, session); + + // Sign deploy + deploy.sign(senderKey); + + // Submit deploy + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + // You can check the deploy status on the block explorer: + // Testnet: https://testnet.cspr.live/transaction/ + // Mainnet: https://cspr.live/transaction/ + console.log( + `View on explorer: https://testnet.cspr.live/transaction/${result.deployHash}` + ); + + return result.deployHash; +}; +``` -const { Keys, CasperClient, CLPublicKey, DeployUtil } = require("casper-js-sdk"); +### Serializing and Deserializing Transactions {#serialize-transactions} -const RPC_API = "http://159.65.203.12:7777/rpc"; -const STATUS_API = "http://159.65.203.12:8888"; +You can serialize transactions to JSON for storage, transmission, or later processing: -const sendTransfer = async ({ from, to, amount }) => { - const casperClient = new CasperClient(RPC_API); +```javascript +import { Transaction } from "casper-js-sdk"; - const folder = path.join("./", "casper_keys"); +// Serialize a transaction to JSON +const serializeTransaction = (transaction) => { + const jsonString = JSON.stringify(transaction.toJSON()); + console.log("Serialized Transaction:", jsonString); - // Read keys from the structure created in #Generating keys - const signKeyPair = Keys.Ed25519.parseKeyFiles(folder + "/" + from + "_public.pem", folder + "/" + from + "_private.pem"); + // Store it, send it over network, etc. + return jsonString; +}; - // networkName can be taken from the status api - const response = await axios.get(STATUS_API + "/status"); +// Deserialize a transaction from JSON +const deserializeTransaction = (json) => { + const transaction = Transaction.fromJSON(json); + console.log("Deserialized Transaction:", transaction); - let networkName = null; + return transaction; +}; - if (response.status == 200) { - networkName = response.data.chainspec_name; - } +// Example usage +const transaction = new NativeTransferBuilder() + .from(privateKey.publicKey) + .target(recipientPublicKey) + .amount("2500000000") + .chainName("casper-test") + .payment(100_000_000) + .build(); - // For native-transfers the payment price is fixed - const paymentAmount = 100000000; +transaction.sign(privateKey); - // transfer_id field in the request to tag the transaction and to correlate it to your back-end storage - const id = 187821; +// Serialize +const serialized = serializeTransaction(transaction); - // gasPrice for native transfers can be set to 1 - const gasPrice = 1; +// Later, deserialize +const restoredTransaction = deserializeTransaction(serialized); - // Time that the deploy will remain valid for, in milliseconds - // The default value is 1800000 ms (30 minutes) - const ttl = 1800000; +// The restored transaction can now be submitted +await rpcClient.putTransaction(restoredTransaction); +``` - let deployParams = new DeployUtil.DeployParams(signKeyPair.publicKey, networkName, gasPrice, ttl); +### Serializing and Deserializing Deploys {#serialize-deploys} - // We create a hex representation of the public key with an added prefix - const toPublicKey = CLPublicKey.fromHex(to); +Similarly, you can serialize and deserialize legacy deploys: - const session = DeployUtil.ExecutableDeployItem.newTransfer(amount, toPublicKey, null, id); +```javascript +import { Deploy } from "casper-js-sdk"; - const payment = DeployUtil.standardPayment(paymentAmount); - const deploy = DeployUtil.makeDeploy(deployParams, session, payment); - const signedDeploy = DeployUtil.signDeploy(deploy, signKeyPair); +// Serialize a deploy to JSON +const serializeDeploy = (deploy) => { + const jsonObject = Deploy.toJSON(deploy); + const jsonString = JSON.stringify(jsonObject); + console.log("Serialized Deploy:", jsonString); - // Here we are sending the signed deploy - return await casperClient.putDeploy(signedDeploy); + // Store it, send it over network, etc. + return jsonString; }; -sendTransfer({ - // Put here the public key of the sender's main purse. Note that it needs to have a balance greater than 2.5 CSPR - from: "", +// Deserialize a deploy from JSON +const deserializeDeploy = (json) => { + const deploy = Deploy.fromJSON(json); + console.log("Deserialized Deploy:", deploy); - // Put here the public key of the recipient's main purse. This account doesn't need to exist. If the key is correctly formatted, the network will create the account when the deploy is sent - to: "", + return deploy; +}; - // Minimal amount is 2.5 CSPR (1 CSPR = 1,000,000,000 motes) - amount: 25000000000, +// Example usage +const deploy = makeCsprTransferDeploy({ + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + transferAmount: "2500000000", }); + +deploy.sign(privateKey); + +// Serialize +const serialized = serializeDeploy(deploy); + +// Later, deserialize +const restoredDeploy = deserializeDeploy(serialized); + +// The restored deploy can now be submitted +await rpcClient.putDeploy(restoredDeploy); +``` + +**Use Cases for Serialization:** + +- Store transactions/deploys in a database +- Send transactions/deploys between different parts of your application +- Create transaction/deploy templates for later signing +- Implement offline transaction signing workflows +- Debug and inspect transaction/deploy structure + +### Using Helper Functions for CSPR Transfers {#helper-functions} + +The SDK provides convenient helper functions for common operations: + +```javascript +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeCsprTransferDeploy, +} from "casper-js-sdk"; + +const sendCsprTransfer = async () => { + // Load private key + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + // Create transfer deploy using helper function + const deploy = makeCsprTransferDeploy({ + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + transferAmount: "2500000000", // 2.5 CSPR in motes + }); + + // Sign deploy + deploy.sign(privateKey); + + // Initialize RPC client and submit + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + // Check deploy status on block explorer + console.log( + `View on explorer: https://testnet.cspr.live/transaction/${result.deployHash}` + ); + + return result.deployHash; +}; +``` + +### Auction Manager Operations {#auction-manager} + +Delegate, undelegate, or redelegate CSPR using the auction manager: + +```javascript +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeAuctionManagerDeploy, + AuctionManagerEntryPoint, +} from "casper-js-sdk"; + +const delegateStake = async () => { + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + const deploy = makeAuctionManagerDeploy({ + contractEntryPoint: AuctionManagerEntryPoint.delegate, + delegatorPublicKeyHex: privateKey.publicKey.toHex(), + validatorPublicKeyHex: "0123456789abcdef...", + amount: "500000000000", // 500 CSPR in motes + }); + + deploy.sign(privateKey); + + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + return result.deployHash; +}; +``` + +### CEP-18 Token Transfers {#cep18-transfers} + +Transfer CEP-18 tokens using the SDK: + +```javascript +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeCep18TransferDeploy, +} from "casper-js-sdk"; + +const transferCep18Token = async () => { + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + const deploy = await makeCep18TransferDeploy({ + contractHash: "hash-of-cep18-contract...", + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + transferAmount: "25000000000", // Amount with decimals + paymentAmount: "3000000000", // 3 CSPR in motes + }); + + deploy.sign(privateKey); + + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + return result.deployHash; +}; ``` -**Note**: At any moment, you can serialize the deploy from this example to JSON to accomplish whatever you want (store it, send it, etc.). +### NFT Transfers {#nft-transfers} -Here is the code you can use to serialize the deploy: +Transfer NFTs using CEP-47 or CEP-78 standards: ```javascript -const jsonFromDeploy = DeployUtil.deployToJson(signedDeploy); +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeNftTransferDeploy, + NFTTokenStandard, +} from "casper-js-sdk"; + +const transferNft = async () => { + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + const deploy = await makeNftTransferDeploy({ + nftStandard: NFTTokenStandard.CEP78, // or NFTTokenStandard.CEP47 + contractPackageHash: "hash-of-nft-contract...", + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + paymentAmount: "3000000000", // 3 CSPR in motes + tokenId: 234, // NFT token ID + }); + + deploy.sign(privateKey); + + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + return result.deployHash; +}; ``` -Then, you can reconstruct the deploy object using this function: +### Using the RPC Client {#rpc-client} + +The RPC client provides access to all Casper network RPC methods: ```javascript -const deployFromJson = DeployUtil.deployFromJson(jsonFromDeploy); +import { HttpHandler, RpcClient } from "casper-js-sdk"; + +const queryNetwork = async () => { + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + // Get deploy information + const deployHash = + "3facbc4133e722c5c5630b6ad2331383ba849ef719da582cc026e9dd85e72ac9"; + const deployResult = await rpcClient.getDeploy(deployHash); + console.log("Deploy Result:", deployResult); + + // Get transaction information (Casper 2.0) + const txHash = + "ef6a3f8f6c6412b9b2a6eb392d1ca6822e32b791ed7da3236dd0d062b2759bb5"; + const txResult = await rpcClient.getTransactionByTransactionHash(txHash); + console.log("Transaction Result:", txResult); + + // Get network status + const status = await rpcClient.getStatus(); + console.log("Network Status:", status); + + // Get account balance + const publicKey = "01ab..."; // Account public key hex + const balance = await rpcClient.queryBalance(publicKey); + console.log("Account Balance:", balance); +}; ``` +### Subscribing to SSE Events {#sse-events} + +Listen to blockchain events using Server-Sent Events: + +```javascript +import { SseClient, EventName } from "casper-js-sdk"; + +const subscribeToEvents = () => { + const sseClient = new SseClient("http://:9999/events"); + + // Subscribe to block added events + sseClient.subscribe(EventName.BlockAddedEventType, (rawEvent) => { + try { + const parsedEvent = rawEvent.parseAsBlockAddedEvent(); + console.log("New Block Hash:", parsedEvent.BlockAdded.blockHash); + console.log("Block Height:", parsedEvent.BlockAdded.blockHeader.height); + } catch (error) { + console.error("Error processing event:", error); + } + }); + + // Subscribe to transaction processed events (Casper 2.0) + sseClient.subscribe(EventName.TransactionProcessedEventType, (rawEvent) => { + try { + const parsedEvent = rawEvent.parseAsTransactionProcessedEvent(); + console.log( + "Transaction Hash:", + parsedEvent.TransactionProcessed.transactionHash + ); + } catch (error) { + console.error("Error processing event:", error); + } + }); + + // Start the client (optionally with last known event ID) + const lastEventID = 1234; // Optional: resume from specific event + sseClient.start(lastEventID); +}; +``` diff --git a/versioned_docs/version-2.0.0/developers/dapps/sdk/script-sdk.md b/versioned_docs/version-2.0.0/developers/dapps/sdk/script-sdk.md index f8230d92d..1c7717ae9 100644 --- a/versioned_docs/version-2.0.0/developers/dapps/sdk/script-sdk.md +++ b/versioned_docs/version-2.0.0/developers/dapps/sdk/script-sdk.md @@ -17,16 +17,22 @@ These packages give you an easy way to install and interact with the correspondi ## Casper SDK for JavaScript {#casper-sdk-for-javascript} -The [TypeScript/JavaScript SDK](https://github.com/casper-ecosystem/casper-js-sdk) allows developers to interact with a Casper network using TypeScript or JavaScript. This section covers different examples of using the Casper JS SDK. +The [TypeScript/JavaScript SDK](https://github.com/casper-ecosystem/casper-js-sdk) allows developers to interact with a Casper network using TypeScript or JavaScript. Version 5.0 represents a complete rewrite of the SDK with full compatibility for Casper 2.0, introducing new types, improved RPC capabilities, and support for both Transactions (Casper 2.0) and Deploys (legacy). ## Installation {#installation} To install this library using Node.js, run the following command: ```bash -npm install casper-js-sdk@next --save +npm install casper-js-sdk --save ``` +**Note**: The `@next` flag is no longer needed as v5.0 is now the stable release. + +## Migration from v2.x {#migration} + +If you're upgrading from v2.x, please refer to the [v2 to v5 Migration Guide](https://github.com/casper-ecosystem/casper-js-sdk/blob/dev/resources/migration-guide-v2-v5.md) for detailed information about breaking changes and how to update your code. + ## Tests {#tests} You can find basic examples for how to use this library in the `test` directory. To run the tests, use this command: @@ -37,137 +43,528 @@ npm run test ## Usage Examples {#usage-examples} -In this section, we outline a couple of essential tasks you can accomplish with the JavaScript SDK: +In this section, we outline essential tasks you can accomplish with the JavaScript SDK: -- Generating account keys -- Sending a transfer +- Generating account keys +- Sending a native transfer (Casper 2.0 Transaction) +- Sending a legacy deploy (backward compatibility) +- Creating CSPR, CEP-18, and NFT transfers +- Working with the RPC client +- Subscribing to SSE events ### Generating Account Keys {#generating-account-keys} -This example shows you how to use the SDK to generate account keys to sign your deploy. +This example shows you how to use the SDK to generate account keys using the new v5 API: ```javascript -const fs = require("fs"); -const path = require("path"); -const { Keys } = require("casper-js-sdk"); - -const createAccountKeys = () => { - // Generating keys - const edKeyPair = Keys.Ed25519.new(); - const { publicKey, privateKey } = edKeyPair; +import { KeyAlgorithm, PrivateKey, PublicKey } from "casper-js-sdk"; - // Create a hexadecimal representation of the public key - const accountAddress = publicKey.toHex(); +const generateKeys = async () => { + // Choose algorithm: KeyAlgorithm.ED25519 or KeyAlgorithm.SECP256K1 + const privateKeyAlgorithm = KeyAlgorithm.ED25519; - // Get the account hash (Uint8Array) from the public key - const accountHash = publicKey.toAccountHash(); + // Generate new private key + const privateKey = await PrivateKey.generate(privateKeyAlgorithm); - // Store keys as PEM files - const publicKeyInPem = edKeyPair.exportPublicKeyInPem(); - const privateKeyInPem = edKeyPair.exportPrivateKeyInPem(); + // Get public key from private key + const publicKey = privateKey.publicKey; - const folder = path.join("./", "casper_keys"); + // Export keys as hex strings + const privateKeyHex = privateKey.toHex(); + const publicKeyHex = publicKey.toHex(); - if (!fs.existsSync(folder)) { - const tempDir = fs.mkdirSync(folder); - } + console.log("Private Key (hex):", privateKeyHex); + console.log("Public Key (hex):", publicKeyHex); - fs.writeFileSync(folder + "/" + accountAddress + "_public.pem", publicKeyInPem); - fs.writeFileSync(folder + "/" + accountAddress + "_private.pem", privateKeyInPem); + return { privateKey, publicKey }; +}; - return accountAddress; +// Recreate private key from hex string +const loadPrivateKey = async (privateKeyHex, algorithm) => { + const privateKey = await PrivateKey.fromHex(privateKeyHex, algorithm); + return privateKey; }; -const newAccountAddress = createAccountKeys(); +// Recreate public key from hex string +const loadPublicKey = (publicKeyHex) => { + const publicKey = PublicKey.fromHex(publicKeyHex); + return publicKey; +}; ``` -After generating the keys with this code, you can add them to the [Casper Wallet Chrome extension](https://www.casperwallet.io/) and use them to sign your transactions. +**Note**: In v5, the key generation API has changed significantly. The old `Keys.Ed25519.new()` pattern is replaced with `PrivateKey.generate()` and related methods. -### Sending a Transfer {#sending-a-transfer} +### Sending a Native Transfer (Casper 2.0) {#sending-a-transfer} -This code block shows you how to define and send a transfer on a Casper network. Replace the `sender-public-key` and `recipient-public-key` in the code below. +This example shows how to create and send a native CSPR transfer using the new Transaction API (Casper 2.0): -The `sendTransfer` function below will return a `transfer-hash` which you can check on https://testnet.cspr.live/. +```javascript +import { + HttpHandler, + RpcClient, + NativeTransferBuilder, + PrivateKey, + KeyAlgorithm, + PublicKey, +} from "casper-js-sdk"; + +const sendNativeTransfer = async () => { + // Initialize RPC client + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + // Load or generate private key + const privateKey = await PrivateKey.generate(KeyAlgorithm.ED25519); + + // Create a native transfer transaction + const transaction = new NativeTransferBuilder() + .from(privateKey.publicKey) + .target( + PublicKey.fromHex( + "0202f5a92ab6da536e7b1a351406f3744224bec85d7acbab1497b65de48a1a707b64" + ) + ) + .amount("2500000000") // Amount in motes (2.5 CSPR) + .id(Date.now()) // Transfer ID for tracking + .chainName("casper-net-1") // Or 'casper-test' for testnet + .payment(100_000_000) // Payment amount in motes + .build(); + + // Sign the transaction + transaction.sign(privateKey); + + try { + // Submit transaction to the network + const result = await rpcClient.putTransaction(transaction); + console.log("Transaction Hash:", result.transactionHash); + + // You can check the transaction status on the block explorer: + // Testnet: https://testnet.cspr.live/transaction/ + // Mainnet: https://cspr.live/transaction/ + console.log( + `View on explorer: https://testnet.cspr.live/transaction/${result.transactionHash}` + ); + + return result.transactionHash; + } catch (error) { + console.error("Transaction failed:", error); + throw error; + } +}; +``` + +### Sending a Legacy Deploy {#sending-legacy-deploy} + +For backward compatibility with Casper 1.5, you can still create and send deploys: ```javascript -const fs = require("fs"); -const path = require("path"); -const axios = require("axios"); -const casperClientSDK = require("casper-js-sdk"); +import { + Deploy, + DeployHeader, + ExecutableDeployItem, + HttpHandler, + PublicKey, + KeyAlgorithm, + PrivateKey, + RpcClient, + TransferDeployItem, +} from "casper-js-sdk"; + +const sendLegacyDeploy = async () => { + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const senderKey = await PrivateKey.generate(KeyAlgorithm.ED25519); + const recipientKey = PublicKey.fromHex( + "010068920746ecf5870e18911EE1fC5db975E0e97fFFcBBF52f5045Ad6C9838D2F" + ); + + const paymentAmount = "10000000000000"; + const transferAmount = "10"; + const transferId = 35; + + // Create session (transfer) + const session = new ExecutableDeployItem(); + session.transfer = TransferDeployItem.newTransfer( + transferAmount, + recipientKey, + undefined, + transferId + ); + + // Create payment + const payment = ExecutableDeployItem.standardPayment(paymentAmount); + + // Create deploy header + const deployHeader = DeployHeader.default(); + deployHeader.account = senderKey.publicKey; + deployHeader.chainName = "casper-test"; + + // Make deploy + const deploy = Deploy.makeDeploy(deployHeader, payment, session); + + // Sign deploy + deploy.sign(senderKey); + + // Submit deploy + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + // You can check the deploy status on the block explorer: + // Testnet: https://testnet.cspr.live/transaction/ + // Mainnet: https://cspr.live/transaction/ + console.log( + `View on explorer: https://testnet.cspr.live/transaction/${result.deployHash}` + ); + + return result.deployHash; +}; +``` -const { Keys, CasperClient, CLPublicKey, DeployUtil } = require("casper-js-sdk"); +### Serializing and Deserializing Transactions {#serialize-transactions} -const RPC_API = "http://159.65.203.12:7777/rpc"; -const STATUS_API = "http://159.65.203.12:8888"; +You can serialize transactions to JSON for storage, transmission, or later processing: -const sendTransfer = async ({ from, to, amount }) => { - const casperClient = new CasperClient(RPC_API); +```javascript +import { Transaction } from "casper-js-sdk"; - const folder = path.join("./", "casper_keys"); +// Serialize a transaction to JSON +const serializeTransaction = (transaction) => { + const jsonString = JSON.stringify(transaction.toJSON()); + console.log("Serialized Transaction:", jsonString); - // Read keys from the structure created in #Generating keys - const signKeyPair = Keys.Ed25519.parseKeyFiles(folder + "/" + from + "_public.pem", folder + "/" + from + "_private.pem"); + // Store it, send it over network, etc. + return jsonString; +}; - // networkName can be taken from the status api - const response = await axios.get(STATUS_API + "/status"); +// Deserialize a transaction from JSON +const deserializeTransaction = (json) => { + const transaction = Transaction.fromJSON(json); + console.log("Deserialized Transaction:", transaction); - let networkName = null; + return transaction; +}; - if (response.status == 200) { - networkName = response.data.chainspec_name; - } +// Example usage +const transaction = new NativeTransferBuilder() + .from(privateKey.publicKey) + .target(recipientPublicKey) + .amount("2500000000") + .chainName("casper-test") + .payment(100_000_000) + .build(); - // For native-transfers the payment price is fixed - const paymentAmount = 100000000; +transaction.sign(privateKey); - // transfer_id field in the request to tag the transaction and to correlate it to your back-end storage - const id = 187821; +// Serialize +const serialized = serializeTransaction(transaction); - // gasPrice for native transfers can be set to 1 - const gasPrice = 1; +// Later, deserialize +const restoredTransaction = deserializeTransaction(serialized); - // Time that the deploy will remain valid for, in milliseconds - // The default value is 1800000 ms (30 minutes) - const ttl = 1800000; +// The restored transaction can now be submitted +await rpcClient.putTransaction(restoredTransaction); +``` - let deployParams = new DeployUtil.DeployParams(signKeyPair.publicKey, networkName, gasPrice, ttl); +### Serializing and Deserializing Deploys {#serialize-deploys} - // We create a hex representation of the public key with an added prefix - const toPublicKey = CLPublicKey.fromHex(to); +Similarly, you can serialize and deserialize legacy deploys: - const session = DeployUtil.ExecutableDeployItem.newTransfer(amount, toPublicKey, null, id); +```javascript +import { Deploy } from "casper-js-sdk"; - const payment = DeployUtil.standardPayment(paymentAmount); - const deploy = DeployUtil.makeDeploy(deployParams, session, payment); - const signedDeploy = DeployUtil.signDeploy(deploy, signKeyPair); +// Serialize a deploy to JSON +const serializeDeploy = (deploy) => { + const jsonObject = Deploy.toJSON(deploy); + const jsonString = JSON.stringify(jsonObject); + console.log("Serialized Deploy:", jsonString); - // Here we are sending the signed deploy - return await casperClient.putDeploy(signedDeploy); + // Store it, send it over network, etc. + return jsonString; }; -sendTransfer({ - // Put here the public key of the sender's main purse. Note that it needs to have a balance greater than 2.5 CSPR - from: "", +// Deserialize a deploy from JSON +const deserializeDeploy = (json) => { + const deploy = Deploy.fromJSON(json); + console.log("Deserialized Deploy:", deploy); - // Put here the public key of the recipient's main purse. This account doesn't need to exist. If the key is correctly formatted, the network will create the account when the deploy is sent - to: "", + return deploy; +}; - // Minimal amount is 2.5 CSPR (1 CSPR = 1,000,000,000 motes) - amount: 25000000000, +// Example usage +const deploy = makeCsprTransferDeploy({ + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + transferAmount: "2500000000", }); + +deploy.sign(privateKey); + +// Serialize +const serialized = serializeDeploy(deploy); + +// Later, deserialize +const restoredDeploy = deserializeDeploy(serialized); + +// The restored deploy can now be submitted +await rpcClient.putDeploy(restoredDeploy); ``` -**Note**: At any moment, you can serialize the deploy from this example to JSON to accomplish whatever you want (store it, send it, etc.). +**Use Cases for Serialization:** + +- Store transactions/deploys in a database +- Send transactions/deploys between different parts of your application +- Create transaction/deploy templates for later signing +- Implement offline transaction signing workflows +- Debug and inspect transaction/deploy structure + +### Using Helper Functions for CSPR Transfers {#helper-functions} -Here is the code you can use to serialize the deploy: +The SDK provides convenient helper functions for common operations: ```javascript -const jsonFromDeploy = DeployUtil.deployToJson(signedDeploy); +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeCsprTransferDeploy, +} from "casper-js-sdk"; + +const sendCsprTransfer = async () => { + // Load private key + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + // Create transfer deploy using helper function + const deploy = makeCsprTransferDeploy({ + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + transferAmount: "2500000000", // 2.5 CSPR in motes + }); + + // Sign deploy + deploy.sign(privateKey); + + // Initialize RPC client and submit + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + // Check deploy status on block explorer + console.log( + `View on explorer: https://testnet.cspr.live/transaction/${result.deployHash}` + ); + + return result.deployHash; +}; ``` -Then, you can reconstruct the deploy object using this function: +### Auction Manager Operations {#auction-manager} + +Delegate, undelegate, or redelegate CSPR using the auction manager: ```javascript -const deployFromJson = DeployUtil.deployFromJson(jsonFromDeploy); +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeAuctionManagerDeploy, + AuctionManagerEntryPoint, +} from "casper-js-sdk"; + +const delegateStake = async () => { + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + const deploy = makeAuctionManagerDeploy({ + contractEntryPoint: AuctionManagerEntryPoint.delegate, + delegatorPublicKeyHex: privateKey.publicKey.toHex(), + validatorPublicKeyHex: "0123456789abcdef...", + amount: "500000000000", // 500 CSPR in motes + }); + + deploy.sign(privateKey); + + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + return result.deployHash; +}; ``` +### CEP-18 Token Transfers {#cep18-transfers} + +Transfer CEP-18 tokens using the SDK: + +```javascript +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeCep18TransferDeploy, +} from "casper-js-sdk"; + +const transferCep18Token = async () => { + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + const deploy = await makeCep18TransferDeploy({ + contractHash: "hash-of-cep18-contract...", + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + transferAmount: "25000000000", // Amount with decimals + paymentAmount: "3000000000", // 3 CSPR in motes + }); + + deploy.sign(privateKey); + + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + return result.deployHash; +}; +``` + +### NFT Transfers {#nft-transfers} + +Transfer NFTs using CEP-47 or CEP-78 standards: + +```javascript +import { + HttpHandler, + RpcClient, + KeyAlgorithm, + PrivateKey, + makeNftTransferDeploy, + NFTTokenStandard, +} from "casper-js-sdk"; + +const transferNft = async () => { + const privateKey = await PrivateKey.fromHex( + "your-private-key-hex", + KeyAlgorithm.ED25519 + ); + + const deploy = await makeNftTransferDeploy({ + nftStandard: NFTTokenStandard.CEP78, // or NFTTokenStandard.CEP47 + contractPackageHash: "hash-of-nft-contract...", + senderPublicKeyHex: privateKey.publicKey.toHex(), + recipientPublicKeyHex: "0123456789abcdef...", + paymentAmount: "3000000000", // 3 CSPR in motes + tokenId: 234, // NFT token ID + }); + + deploy.sign(privateKey); + + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + const result = await rpcClient.putDeploy(deploy); + console.log("Deploy Hash:", result.deployHash); + + return result.deployHash; +}; +``` + +### Using the RPC Client {#rpc-client} + +The RPC client provides access to all Casper network RPC methods: + +```javascript +import { HttpHandler, RpcClient } from "casper-js-sdk"; + +const queryNetwork = async () => { + const rpcHandler = new HttpHandler("http://:7777/rpc"); + const rpcClient = new RpcClient(rpcHandler); + + // Get deploy information + const deployHash = + "3facbc4133e722c5c5630b6ad2331383ba849ef719da582cc026e9dd85e72ac9"; + const deployResult = await rpcClient.getDeploy(deployHash); + console.log("Deploy Result:", deployResult); + + // Get transaction information (Casper 2.0) + const txHash = + "ef6a3f8f6c6412b9b2a6eb392d1ca6822e32b791ed7da3236dd0d062b2759bb5"; + const txResult = await rpcClient.getTransactionByTransactionHash(txHash); + console.log("Transaction Result:", txResult); + + // Get network status + const status = await rpcClient.getStatus(); + console.log("Network Status:", status); + + // Get account balance + const publicKey = "01ab..."; // Account public key hex + const balance = await rpcClient.queryBalance(publicKey); + console.log("Account Balance:", balance); +}; +``` + +### Subscribing to SSE Events {#sse-events} + +Listen to blockchain events using Server-Sent Events: + +```javascript +import { SseClient, EventName } from "casper-js-sdk"; + +const subscribeToEvents = () => { + const sseClient = new SseClient("http://:9999/events"); + + // Subscribe to block added events + sseClient.subscribe(EventName.BlockAddedEventType, (rawEvent) => { + try { + const parsedEvent = rawEvent.parseAsBlockAddedEvent(); + console.log("New Block Hash:", parsedEvent.BlockAdded.blockHash); + console.log("Block Height:", parsedEvent.BlockAdded.blockHeader.height); + } catch (error) { + console.error("Error processing event:", error); + } + }); + + // Subscribe to transaction processed events (Casper 2.0) + sseClient.subscribe(EventName.TransactionProcessedEventType, (rawEvent) => { + try { + const parsedEvent = rawEvent.parseAsTransactionProcessedEvent(); + console.log( + "Transaction Hash:", + parsedEvent.TransactionProcessed.transactionHash + ); + } catch (error) { + console.error("Error processing event:", error); + } + }); + + // Start the client (optionally with last known event ID) + const lastEventID = 1234; // Optional: resume from specific event + sseClient.start(lastEventID); +}; +``` + +## Key Changes in v5 {#key-changes} + +1. **New Key Management API**: `PrivateKey` and `PublicKey` classes replace the old `Keys` API +2. **Transaction Support**: New `Transaction` and builder classes for Casper 2.0 +3. **Improved Type System**: Complete TypeScript rewrite with better type safety +4. **RPC Client Updates**: New methods supporting both Casper 1.5 and 2.0 +5. **Helper Functions**: More utility functions like `makeCsprTransferDeploy`, `makeAuctionManagerDeploy` +6. **SSE Improvements**: Enhanced event handling and parsing +7. **Backward Compatibility**: Continued support for legacy Deploy system + +For comprehensive information about all changes, please refer to the [official migration guide](https://github.com/casper-ecosystem/casper-js-sdk/blob/dev/resources/migration-guide-v2-v5.md) and [full documentation](https://casper-ecosystem.github.io/casper-js-sdk/).