rootchain-sdk 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 RootChain
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ # rootchain-sdk
2
+
3
+ <div align="center">
4
+ <h3>The Official TypeScript SDK for RootChain</h3>
5
+ <p>Communicate with RootChain nodes, deploy WASM smart contracts, and construct deterministic offline transactions seamlessly from any JavaScript environment.</p>
6
+
7
+ [![Version](https://img.shields.io/npm/v/rootchain-sdk.svg)](https://npmjs.org/package/rootchain-sdk)
8
+ [![TypeScript](https://img.shields.io/badge/Language-TypeScript-blue.svg)]()
9
+ [![License](https://img.shields.io/badge/License-MIT-green.svg)]()
10
+ </div>
11
+
12
+ ---
13
+
14
+ The `rootchain-sdk` provides a clean, heavily-typed API wrapper over the `rootchain-rpc` JSON-RPC 2.0 endpoints. It empowers developers to build rich, reactive Web3 interfaces on top of the RootChain ecosystem with absolute minimal overhead.
15
+
16
+ ## 📦 Installation
17
+
18
+ This package is optimized for modern toolchains (Node >= 18, Bun, Vite).
19
+
20
+ ```bash
21
+ npm install rootchain-sdk
22
+ # or
23
+ bun add rootchain-sdk
24
+ # or
25
+ yarn add rootchain-sdk
26
+ # or
27
+ pnpm add rootchain-sdk
28
+ ```
29
+
30
+ ## âš¡ Core Features
31
+
32
+ * **100% Type-Safe**: Comprehensive types for transactions, blocks, receipts, and RRC network structs.
33
+ * **Offline Transaction Building**: Deterministically serialize and sign payloads completely offline, mitigating key-leakage attacks.
34
+ * **JSON-RPC Provider Wrapper**: Native `JsonRpcProvider` for network data, account querying, and telemetry extraction.
35
+ * **Key Derivation**: Securely derive Ed25519 paths via standard BIP-39 mnemonic recovery phrases.
36
+ * **WASM Deployment Ready**: Methods and structures natively adapted for deploying and querying sandboxed webassembly bytecodes.
37
+
38
+ ## 🚀 Quick Start Guide
39
+
40
+ ### 1. Initialize the Provider
41
+
42
+ Connect directly to your local node or remote `rootchain-rpc` endpoint:
43
+
44
+ ```typescript
45
+ import { JsonRpcProvider } from 'rootchain-sdk';
46
+
47
+ // Initialize the generic provider
48
+ const provider = new JsonRpcProvider('http://localhost:8545');
49
+
50
+ // Fetch network status
51
+ const { height, chain_id } = await provider.getChainInfo();
52
+ console.log(`Connected to ${chain_id} at block ${height}`);
53
+ ```
54
+
55
+ ### 2. Wallet & Account Derivation
56
+
57
+ Derive your private keys deterministically and check your native balance securely:
58
+
59
+ ```typescript
60
+ import { Wallet } from 'rootchain-sdk';
61
+
62
+ // Instantiate a wallet connected to the provider
63
+ const privateKeyHex = "0x4f3c..."; // Ensure 32-bytes representation
64
+ const wallet = new Wallet(privateKeyHex, provider);
65
+
66
+ // Resolve public key representation
67
+ const address = await wallet.getAddress();
68
+
69
+ // Retrieve canonical balance and account nonce
70
+ const { balance, nonce } = await provider.getBalance(address);
71
+ console.log(`Remaining Balance: ${balance} micro-ROOT`);
72
+ ```
73
+
74
+ ### 3. Issue a Raw Transaction
75
+
76
+ Seamlessly instruct the provider to broadcast signed `Transfer` transitions directly to the PoA network:
77
+
78
+ ```typescript
79
+ const txReceipt = await wallet.sendTransaction({
80
+ tx_type: "Transfer",
81
+ to: "0x8888...", // 32-byte recipient Hash
82
+ amount: 1000000000000n, // BigInt for safe u128 handling
83
+ fee: 1000n, // Network execution fee
84
+ payload: new Uint8Array() // Zero-length buffer for standardized transfers
85
+ });
86
+
87
+ console.log(`Transaction successfully queued with hash: ${txReceipt.hash}`);
88
+
89
+ // Optionally, await network determinism
90
+ await provider.waitForTransaction(txReceipt.hash);
91
+ console.log('Transaction explicitly finalized within an immutable block!');
92
+ ```
93
+
94
+ ## 📚 Advanced Documentation
95
+
96
+ ### Submitting Equivocation Proofs
97
+ The SDK provides a built-in helper for submitting proofs of validator misbehavior:
98
+
99
+ ```typescript
100
+ const proof = {
101
+ validator: "0xaddr...",
102
+ height: 500,
103
+ round: 1,
104
+ hash_a: "0x...",
105
+ signature_a: "0x...",
106
+ hash_b: "0x...",
107
+ signature_b: "0x..."
108
+ };
109
+
110
+ const { hash } = await provider.submitEquivocationProof(proof);
111
+ console.log(`Equivocation proof submitted: ${hash}`);
112
+ ```
113
+
114
+ For deeper operational hooks into `rootchain-std` execution contracts (`ContractCall` and `ContractDeploy`), refer to the advanced ecosystem tutorials outlined in the `/docs` directory.
@@ -0,0 +1,3 @@
1
+ export * from "./provider.js";
2
+ export * from "./signer.js";
3
+ export * from "./wallet.js";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./provider.js";
2
+ export * from "./signer.js";
3
+ export * from "./wallet.js";
@@ -0,0 +1,127 @@
1
+ export interface ChainInfo {
2
+ height: number;
3
+ best_hash: string;
4
+ validators: string[];
5
+ slashed: string[];
6
+ chain_id: number;
7
+ }
8
+ export interface BalanceInfo {
9
+ balance: string;
10
+ nonce: number;
11
+ }
12
+ export interface Transaction {
13
+ tx_type: string;
14
+ from: number[] | string;
15
+ to: number[] | string;
16
+ amount: string;
17
+ fee: string;
18
+ nonce: number;
19
+ payload: number[] | string;
20
+ signature: number[] | string;
21
+ }
22
+ export interface ContractEvent {
23
+ contract_address: string;
24
+ topics: string[];
25
+ data: string;
26
+ }
27
+ export interface TransactionReceipt {
28
+ transaction: Transaction;
29
+ block_height: number;
30
+ block_hash: string;
31
+ events: ContractEvent[];
32
+ gas_used: string;
33
+ success: boolean;
34
+ error?: string;
35
+ transaction_hash?: string;
36
+ }
37
+ export interface EquivocationProof {
38
+ validator: string;
39
+ height: number;
40
+ round: number;
41
+ hash_a: string;
42
+ signature_a: string;
43
+ hash_b: string;
44
+ signature_b: string;
45
+ }
46
+ export interface Block {
47
+ header: {
48
+ height: number;
49
+ prev_hash: number[] | string;
50
+ merkle_root: number[] | string;
51
+ state_root: number[] | string;
52
+ proposer: number[] | string;
53
+ timestamp: number;
54
+ signature: number[] | string;
55
+ };
56
+ transactions: Transaction[];
57
+ }
58
+ export interface GovernanceProposal {
59
+ id: string;
60
+ type: string;
61
+ params: any;
62
+ status: 'Active' | 'Passed' | 'Failed';
63
+ signatures: number;
64
+ threshold: number;
65
+ description: string;
66
+ created_at: number;
67
+ }
68
+ export interface PeerInfo {
69
+ peer_id: string;
70
+ address: string;
71
+ rtt_ms: number;
72
+ height: number;
73
+ }
74
+ export interface ContractCode {
75
+ address: string;
76
+ bytecode: string;
77
+ bytecode_hex: string;
78
+ }
79
+ export interface StorageValue {
80
+ key: string;
81
+ value: string | null;
82
+ }
83
+ export declare class JsonRpcProvider {
84
+ readonly url: string;
85
+ constructor(url?: string);
86
+ send<T>(method: string, params?: any[]): Promise<T>;
87
+ getBalance(address: string): Promise<{
88
+ balance: string;
89
+ nonce: number;
90
+ }>;
91
+ sendRawTransaction(tx: any): Promise<{
92
+ hash: string;
93
+ contractAddress?: string;
94
+ }>;
95
+ getChainInfo(): Promise<ChainInfo>;
96
+ getFinalizedBlock(): Promise<Block | null>;
97
+ submitProposal(proposalHex: string, fromAddress: string, fee?: number): Promise<{
98
+ status: string;
99
+ tx_hash: string;
100
+ }>;
101
+ getGovernanceProposals(): Promise<GovernanceProposal[]>;
102
+ getPeerInfo(): Promise<PeerInfo[]>;
103
+ getCode(address: string): Promise<ContractCode>;
104
+ getStorageAt(address: string, key: string): Promise<StorageValue>;
105
+ getBlock(id: string | number): Promise<Block | null>;
106
+ getBlocks(endHeight?: number, limit?: number): Promise<Block[]>;
107
+ getTransaction(hash: string): Promise<TransactionReceipt | null>;
108
+ getTransactionsByAddress(address: string, limit?: number, offset?: number): Promise<TransactionReceipt[]>;
109
+ getLogs(filter: {
110
+ address?: string;
111
+ fromBlock?: number;
112
+ toBlock?: number;
113
+ }): Promise<any[]>;
114
+ submitEquivocationProof(proof: EquivocationProof): Promise<{
115
+ hash: string;
116
+ }>;
117
+ getMetadata(address: string): Promise<{
118
+ metadata: string;
119
+ } | null>;
120
+ waitForTransaction(hash: string, timeoutMs?: number): Promise<TransactionReceipt>;
121
+ }
122
+ export declare class EventDecoder {
123
+ /**
124
+ * Decodes a raw contract event using the contract's metadata schema.
125
+ */
126
+ static decode(event: ContractEvent, metadataJson: string | any): any;
127
+ }
@@ -0,0 +1,131 @@
1
+ export class JsonRpcProvider {
2
+ url;
3
+ constructor(url) {
4
+ // @ts-ignore
5
+ const envUrl = typeof process !== 'undefined' ? process.env.VITE_RPC_URL || process.env.RPC_URL : undefined;
6
+ // @ts-ignore
7
+ const metaUrl = typeof import.meta !== 'undefined' && import.meta.env ? import.meta.env.VITE_RPC_URL : undefined;
8
+ this.url = url || metaUrl || envUrl || 'http://127.0.0.1:8545';
9
+ }
10
+ async send(method, params = []) {
11
+ const response = await fetch(this.url, {
12
+ method: "POST",
13
+ headers: { "Content-Type": "application/json" },
14
+ body: JSON.stringify({
15
+ jsonrpc: "2.0",
16
+ method,
17
+ params,
18
+ id: Date.now(),
19
+ }),
20
+ });
21
+ if (!response.ok) {
22
+ throw new Error(`HTTP Error: ${response.status}`);
23
+ }
24
+ const data = await response.json();
25
+ if (data.error) {
26
+ throw new Error(data.error.message);
27
+ }
28
+ return data.result;
29
+ }
30
+ async getBalance(address) {
31
+ return this.send("rootchain_getBalance", [address]);
32
+ }
33
+ async sendRawTransaction(tx) {
34
+ const result = await this.send("rootchain_sendRawTransaction", [tx]);
35
+ return {
36
+ hash: result.hash,
37
+ contractAddress: result.contractAddress || result.contract_address,
38
+ };
39
+ }
40
+ getChainInfo() {
41
+ return this.send('rootchain_getChainInfo');
42
+ }
43
+ getFinalizedBlock() {
44
+ return this.send('rootchain_getFinalizedBlock');
45
+ }
46
+ submitProposal(proposalHex, fromAddress, fee = 100) {
47
+ return this.send('rootchain_submitProposal', [proposalHex, fromAddress, fee]);
48
+ }
49
+ getGovernanceProposals() {
50
+ return this.send('rootchain_listProposals');
51
+ }
52
+ getPeerInfo() {
53
+ return this.send('rootchain_getNetworkTopology');
54
+ }
55
+ getCode(address) {
56
+ return this.send('rootchain_getCode', [address]);
57
+ }
58
+ getStorageAt(address, key) {
59
+ return this.send('rootchain_getStorageAt', [address, key]);
60
+ }
61
+ getBlock(id) {
62
+ return this.send('rootchain_getBlock', [id]);
63
+ }
64
+ async getBlocks(endHeight, limit = 20) {
65
+ // If no endHeight passed, first get the current chain height
66
+ if (endHeight === undefined) {
67
+ const info = await this.getChainInfo().catch(() => null);
68
+ endHeight = info?.height ?? 0;
69
+ }
70
+ return this.send('rootchain_getBlocks', [endHeight, limit]);
71
+ }
72
+ getTransaction(hash) {
73
+ return this.send('rootchain_getTransaction', [hash]);
74
+ }
75
+ getTransactionsByAddress(address, limit = 10, offset = 0) {
76
+ return this.send('rootchain_getTransactionsByAddress', [address, limit, offset]);
77
+ }
78
+ async getLogs(filter) {
79
+ return this.send("rootchain_getLogs", [filter]);
80
+ }
81
+ async submitEquivocationProof(proof) {
82
+ return this.send("rootchain_submitEquivocationProof", [proof]);
83
+ }
84
+ async getMetadata(address) {
85
+ return this.send('rootchain_getMetadata', [address]);
86
+ }
87
+ async waitForTransaction(hash, timeoutMs = 60000) {
88
+ const start = Date.now();
89
+ while (Date.now() - start < timeoutMs) {
90
+ const receipt = await this.getTransaction(hash);
91
+ if (receipt)
92
+ return receipt;
93
+ await new Promise(resolve => setTimeout(resolve, 1000));
94
+ }
95
+ throw new Error(`Timeout waiting for transaction ${hash}`);
96
+ }
97
+ }
98
+ export class EventDecoder {
99
+ /**
100
+ * Decodes a raw contract event using the contract's metadata schema.
101
+ */
102
+ static decode(event, metadataJson) {
103
+ try {
104
+ const metadata = typeof metadataJson === 'string' ? JSON.parse(metadataJson) : metadataJson;
105
+ if (!metadata || !metadata.events)
106
+ return event;
107
+ // Simple matching: find event with same number of topics
108
+ for (const [name, schema] of Object.entries(metadata.events)) {
109
+ const s = schema;
110
+ if (event.topics.length === s.topics.length) {
111
+ const params = {};
112
+ s.topics.forEach((topicName, i) => {
113
+ params[topicName] = event.topics[i];
114
+ });
115
+ if (s.data) {
116
+ params[s.data] = event.data;
117
+ }
118
+ return {
119
+ name,
120
+ address: event.contract_address,
121
+ parameters: params
122
+ };
123
+ }
124
+ }
125
+ }
126
+ catch (e) {
127
+ console.error("Failed to decode event:", e);
128
+ }
129
+ return event;
130
+ }
131
+ }
@@ -0,0 +1,19 @@
1
+ import type { JsonRpcProvider } from "./provider.js";
2
+ export interface TransactionRequest {
3
+ tx_type: string;
4
+ from?: string;
5
+ to?: string;
6
+ amount?: bigint | string | number;
7
+ fee?: bigint | string | number;
8
+ nonce?: number;
9
+ payload?: Uint8Array;
10
+ }
11
+ export interface Signer {
12
+ getAddress(): Promise<string>;
13
+ signTransaction(tx: TransactionRequest): Promise<string>;
14
+ sendTransaction(tx: TransactionRequest): Promise<{
15
+ hash: string;
16
+ contractAddress?: string;
17
+ }>;
18
+ connect(provider: JsonRpcProvider): Signer;
19
+ }
package/dist/signer.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"root":["../src/index.ts","../src/provider.ts","../src/signer.ts","../src/wallet.ts"],"version":"5.9.3"}
@@ -0,0 +1,17 @@
1
+ import type { JsonRpcProvider } from "./provider.js";
2
+ import type { Signer, TransactionRequest } from "./signer.js";
3
+ export declare class Wallet implements Signer {
4
+ private address?;
5
+ readonly privateKeyHex: string;
6
+ readonly provider?: JsonRpcProvider;
7
+ constructor(privateKeyHex: string, provider?: JsonRpcProvider);
8
+ connect(provider: JsonRpcProvider): Wallet;
9
+ getAddress(): Promise<string>;
10
+ getContractAddress(nonce: number): Promise<string>;
11
+ signTransaction(tx: TransactionRequest): Promise<string>;
12
+ sendTransaction(tx: TransactionRequest): Promise<{
13
+ hash: string;
14
+ contractAddress?: string;
15
+ }>;
16
+ private hexToBytes;
17
+ }
package/dist/wallet.js ADDED
@@ -0,0 +1,69 @@
1
+ import { get_address_from_key, sign_transaction, get_contract_address } from "rootchain-wasm";
2
+ export class Wallet {
3
+ address;
4
+ privateKeyHex;
5
+ provider;
6
+ constructor(privateKeyHex, provider) {
7
+ this.privateKeyHex = privateKeyHex;
8
+ this.provider = provider;
9
+ }
10
+ connect(provider) {
11
+ return new Wallet(this.privateKeyHex, provider);
12
+ }
13
+ async getAddress() {
14
+ if (this.address)
15
+ return this.address;
16
+ const cleanKey = this.privateKeyHex.replace("0x", "");
17
+ const result = get_address_from_key(cleanKey);
18
+ this.address = typeof result === "string" ? result : result.toString();
19
+ return this.address;
20
+ }
21
+ async getContractAddress(nonce) {
22
+ const address = await this.getAddress();
23
+ return get_contract_address(address, BigInt(nonce));
24
+ }
25
+ async signTransaction(tx) {
26
+ // Fill missing fields
27
+ const fullTx = {
28
+ tx_type: tx.tx_type,
29
+ from: Array(32).fill(0), // WASM overwrites this anyway based on private key
30
+ to: tx.to ? this.hexToBytes(tx.to) : Array(32).fill(0),
31
+ amount: tx.amount?.toString() ?? "0",
32
+ fee: tx.fee?.toString() ?? "1000",
33
+ nonce: tx.nonce ?? 1,
34
+ payload: tx.payload ? Array.from(tx.payload) : [],
35
+ signature: Array(64).fill(0)
36
+ };
37
+ const cleanKey = this.privateKeyHex.replace("0x", "");
38
+ return sign_transaction(JSON.stringify(fullTx), cleanKey);
39
+ }
40
+ async sendTransaction(tx) {
41
+ if (!this.provider) {
42
+ throw new Error("Wallet is not connected to a Provider");
43
+ }
44
+ const address = await this.getAddress();
45
+ // Auto-fetch nonce if not provided
46
+ if (tx.nonce === undefined) {
47
+ const { nonce } = await this.provider.getBalance(address);
48
+ tx.nonce = nonce + 1; // Expected nonce is current recorded nonce + 1
49
+ }
50
+ let predictedAddress;
51
+ if (tx.tx_type === "ContractDeploy") {
52
+ predictedAddress = await this.getContractAddress(tx.nonce);
53
+ }
54
+ const signedTxJson = await this.signTransaction(tx);
55
+ const result = await this.provider.sendRawTransaction(JSON.parse(signedTxJson));
56
+ return {
57
+ hash: result.hash,
58
+ contractAddress: result.contractAddress || predictedAddress
59
+ };
60
+ }
61
+ hexToBytes(hex) {
62
+ const cleanHex = hex.replace("0x", "");
63
+ const bytes = new Uint8Array(cleanHex.length / 2);
64
+ for (let i = 0; i < cleanHex.length; i += 2) {
65
+ bytes[i / 2] = parseInt(cleanHex.substring(i, i + 2), 16);
66
+ }
67
+ return Array.from(bytes);
68
+ }
69
+ }
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "rootchain-sdk",
3
+ "version": "1.0.1",
4
+ "description": "The Official TypeScript SDK for RootChain - High-precision RPC client.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md",
11
+ "LICENSE"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc -b",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/BronzonTech-Cloud/rootchain.git"
20
+ },
21
+ "keywords": [
22
+ "rootchain",
23
+ "blockchain",
24
+ "sdk",
25
+ "u128",
26
+ "wasm",
27
+ "wallet"
28
+ ],
29
+ "author": "Charles Bronzon",
30
+ "license": "MIT",
31
+ "bugs": {
32
+ "url": "https://github.com/BronzonTech-Cloud/rootchain/issues"
33
+ },
34
+ "homepage": "https://github.com/BronzonTech-Cloud/rootchain#readme",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "default": "./dist/index.js"
39
+ }
40
+ },
41
+ "dependencies": {
42
+ "rootchain-wasm": "^1.0.1"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "^5.0.0"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ }
50
+ }