JavaScript/TypeScript utilities for interacting with Odra smart contracts on the Casper Network.
Built on top of casper-js-sdk.
npm install @casper-ecosystem/odra-js-client casper-js-sdkimport { OdraClient } from '@casper-ecosystem/odra-js-client';
import { Args, CLValue } from 'casper-js-sdk';
import { readFileSync } from 'fs';
const client = new OdraClient(
'http://<Node Address>:7777/rpc',
'casper-test'
);
client.setContractHash(
'834d3e29...', // bare hex, "contract-hash-...", or "hash-..." all accepted
'f1127fd1...', // contract package hash (required for write operations)
);
// Read a Var<T> field
const name = await client.getVar('name');
console.log(name?.toString()); // e.g. "MyToken"
// Read a Mapping<K, V> entry
const balance = await client.getMappingItem('balances', 'account-hash-abc...');
// Call a non-payable entry point
await client.call(
'transfer',
Args.fromMap({
recipient: CLValue.newCLString('account-hash-...'),
amount: CLValue.newCLUInt256('1000000000'),
}),
{
sender: publicKey,
paymentAmount: '2500000000',
signingKeys: [privateKey],
},
);
// Call a payable entry point via the Odra proxy WASM
const proxyWasm = new Uint8Array(readFileSync('proxy_caller.wasm'));
await client.callPayable(
'stake',
Args.fromMap({}),
'2000000000000', // amount in motes
proxyWasm,
{
sender: publicKey,
paymentAmount: '5000000000',
signingKeys: [privateKey],
},
);High-level client. Wraps all utilities into a single class.
| Method | Description |
|---|---|
setContractHash(hash, packageHash?) |
Configure target contract. Accepts bare hex or prefixed strings. Returns this. |
resolveContractHash() |
Auto-resolve and cache the latest contract hash from the package hash. |
getNamedKeys() |
List all named keys on the contract. |
getVar(name) |
Read an Odra Var<T> field by named key name. |
getMappingItem(name, key) |
Read one entry from an Odra Mapping<K,V> dictionary. |
getState(index, key?, blockHeight?) |
Read raw bytes from Odra's internal state dictionary by field index. |
call(entryPoint, args, params) |
Submit a non-payable contract call transaction. |
callPayable(entryPoint, innerArgs, amount, wasm, params) |
Submit a payable call via the Odra proxy WASM pattern. |
Sequential byte-stream decoder for packed Odra struct state.
Odra stores every Var<T> / Mapping<K,V> value as Casper-serialised bytes inside a List<U8> CLValue. The decoder skips the 4-byte count prefix automatically.
Fields must be read in the same order they are declared in the Rust struct. Reading out of order will silently produce incorrect values.
import { getOdraState, OdraStateDecoder } from '@casper-ecosystem/odra-js-client';
import { RpcClient, HttpHandler } from 'casper-js-sdk';
const rpc = new RpcClient(new HttpHandler('http://<Node Address>:7777/rpc'));
const raw = await getOdraState(rpc, contractHash, BONDING_CURVE_INDEX, tokenKey);
const dec = new OdraStateDecoder(raw);
const csprReserve = dec.readU256();
const initialPrice = dec.readU256();
const graduated = dec.readBool();
const graduatedAt = dec.readOptionU64(); // bigint | null| Method | CL type | Return |
|---|---|---|
readBool() |
Bool |
boolean |
readU8() |
U8 |
number |
readU32() |
U32 |
number |
readU64() |
U64 |
bigint |
readU128() |
U128 |
bigint |
readU256() |
U256 |
bigint |
readU512() |
U512 |
bigint |
readString() |
String |
string |
readKey() |
Key |
string (prefixed) |
readKeyBytes() |
Key |
Uint8Array (33 bytes) |
readOption(fn) |
Option<T> |
T | null |
readOptionU64() |
Option<U64> |
bigint | null |
readOptionU256() |
Option<U256> |
bigint | null |
readOptionString() |
Option<String> |
string | null |
readFixedBytes(n) |
ByteArray(N) |
Uint8Array |
readBytes() |
Bytes / List<U8> |
Uint8Array |
import { isOdraProxyCall, parseOdraProxyCallArgs, buildOdraProxyCallArgs } from '@casper-ecosystem/odra-js-client';
// Detect an Odra proxy call in a transaction scanner
if (isOdraProxyCall(tx.payload.fields.args)) {
const { packageHash, entryPoint, innerArgs, amount } = parseOdraProxyCallArgs(
tx.payload.fields.args,
);
}
// Build outer args for a proxy WASM transaction
const outerArgs = buildOdraProxyCallArgs(
packageHashHex,
'stake',
innerArgs,
'2000000000000', // omit for non-payable
);import {
getOdraContractNamedKeys,
getOdraContractVar,
getOdraContractMappingItem,
getOdraState,
deriveOdraStateKey,
getContractHashFromPackage,
} from '@casper-ecosystem/odra-js-client';Odra payable entry points require a Session transaction (inline WASM) instead of a standard contract call. This is because StoredVersionedContractByPackageHash cannot transfer CSPR from the caller's main purse to the contract's purse.
The proxy WASM accepts:
| Arg | CL type | Description |
|---|---|---|
package_hash |
ByteArray(32) |
Target contract package hash |
entry_point |
String |
Entry point name |
args |
List<U8> |
Casper-serialised inner Args |
attached_value |
U512 |
Amount the contract reads via env().attached_value() |
amount |
U512 |
Amount the Casper node uses to perform the actual transfer |
amountandattached_valuecarry the same mote value but serve different purposes.
npm install
npm test # run unit tests
npm run build # compile to dist/