Skip to content

Commit

Permalink
Merge pull request #82 from casper-ecosystem/feature_next/more-rpc
Browse files Browse the repository at this point in the history
more rpc methods implemented
  • Loading branch information
hoffmannjan authored Jul 13, 2021
2 parents 8dece53 + dd63567 commit 3056131
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 69 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to casper-js-sdk.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 2.1.0

### Fixed

- `state-get-item` due to RPC changes
- `CLList` as empty list initialization from JSON

### Added

- `getBlockTransfers`, `getEraInfoBySwitchBlock`, `getEraInfoBySwitchBlockHeight` methods to `CasperServiceByJsonRPC`

## 2.0.1

### Changed
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "casper-js-sdk",
"version": "2.0.1",
"version": "2.1.0",
"license": "Apache 2.0",
"description": "SDK to interact with the Casper blockchain",
"homepage": "https://github.com/casper-ecosystem/casper-js-sdk#README.md",
Expand All @@ -19,6 +19,7 @@
"build": "webpack --config webpack.config.js",
"clean": "rm -rf ./dist",
"~build": "tsc --watch",
"test:nctl": "TS_NODE_FILES=true mocha -r ts-node/register test/nctl/*.test.ts",
"test": "TS_NODE_FILES=true mocha -r ts-node/register test/**/*.test.ts src/lib/CLValue/*.test.ts",
"test:coverage": "nyc npm run test",
"docs": "typedoc --out docs/ src",
Expand Down
18 changes: 18 additions & 0 deletions src/lib/CLValue/List.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
CLListType,
CLBool,
CLBoolType,
CLStringType,
CLU8,
CLI32,
CLI32Type
Expand Down Expand Up @@ -161,6 +162,23 @@ describe('CLValue List implementation', () => {
expect(fromBytes).to.be.deep.eq(myList);
});

it('Runs toJSON() / fromJSON() on empty list', () => {
const myList = new CLList(new CLStringType());

const json = CLValueParsers.toJSON(myList).unwrap();

const expectedJson = JSON.parse(
'{"bytes":"00000000","cl_type":{"List": "String" }}'
);

const newList1 = CLValueParsers.fromJSON(json).unwrap();
const newList2 = CLValueParsers.fromJSON(expectedJson).unwrap();

expect(json).to.be.deep.eq(expectedJson);
expect(newList1).to.be.deep.eq(myList);
expect(newList2).to.be.deep.eq(myList);
});

it('Runs toJSON() / fromJSON() properly', () => {
const myList = new CLList([
new CLList([new CLBool(true), new CLBool(false)]),
Expand Down
5 changes: 5 additions & 0 deletions src/lib/CLValue/List.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ export class CLListBytesParser extends CLValueBytesParsers {
remainder = vRem;
}

// Support for creating empty lists from bytes
if (vec.length === 0) {
return resultHelper(Ok(new CLList(listType.inner)), remainder);
}

return resultHelper(Ok(new CLList(vec)), remainder);
}
}
Expand Down
127 changes: 121 additions & 6 deletions src/lib/StoredValue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { jsonArrayMember, jsonMember, jsonObject } from 'typedjson';
import { CLValue } from './CLValue';
import { CLValue, CLType, CLValueParsers, matchTypeToCLType } from './CLValue';

@jsonObject
class NamedKey {
Expand Down Expand Up @@ -74,8 +74,14 @@ export class TransferJson {
public gas: string;

// User-defined id
@jsonMember({ constructor: String, preserveNull: true })
public id: string | null;
@jsonMember({ constructor: Number, preserveNull: true })
public id: number | null;
}

@jsonObject
export class Transfers {
@jsonArrayMember(TransferJson)
transfers: TransferJson[];
}

@jsonObject
Expand Down Expand Up @@ -153,6 +159,45 @@ export class EraInfoJson {
public seigniorageAllocations: SeigniorageAllocation[];
}

/**
* Named CLType arguments
*/
@jsonObject
export class NamedCLTypeArg {
@jsonMember({ constructor: String })
public name: string;

@jsonMember({
name: 'cl_type',
deserializer: json => matchTypeToCLType(json)
})
public clType: CLType;
}

/**
* Entry point metadata
*/
@jsonObject
export class EntryPoint {
@jsonMember({ constructor: String })
public access: string;

@jsonMember({ name: 'entry_point_type', constructor: String })
public entryPointType: string;

@jsonMember({ constructor: String })
public name: string;

@jsonMember({
name: 'cl_type',
deserializer: json => matchTypeToCLType(json)
})
public ret: string;

@jsonArrayMember(NamedCLTypeArg)
public args: NamedCLTypeArg[];
}

/**
* Contract metadata.
*/
Expand All @@ -164,15 +209,85 @@ export class ContractMetadataJson {
@jsonMember({ name: 'contract_wasm_hash', constructor: String })
public contractWasmHash: string;

@jsonArrayMember(EntryPoint, { name: 'entry_points' })
public entrypoints: EntryPoint[];

@jsonMember({ name: 'protocol_version', constructor: String })
public protocolVersion: string;

@jsonArrayMember(NamedKey, { name: 'named_keys' })
public namedKeys: NamedKey[];
}

/**
* Contract Version.
*/
@jsonObject
export class ContractVersionJson {
@jsonMember({ name: 'protocol_version_major', constructor: Number })
public protocolVersionMajor: number;

@jsonMember({ name: 'contract_version', constructor: Number })
public contractVersion: number;

@jsonMember({ name: 'contract_hash', constructor: String })
public contractHash: string;
}

/**
* Disabled Version.
*/
@jsonObject
export class DisabledVersionJson {
@jsonMember({ name: 'protocol_version_major', constructor: Number })
public accessKey: number;

@jsonMember({ name: 'contract_version', constructor: Number })
public contractVersion: number;
}

/**
* Groups.
*/
@jsonObject
export class GroupsJson {
@jsonMember({ name: 'group', constructor: String })
public group: string;

@jsonMember({ name: 'keys', constructor: String })
public keys: string;
}

/**
* Contract Package.
*/
@jsonObject
export class ContractPackageJson {
@jsonMember({ name: 'access_key', constructor: String })
public accessKey: string;

@jsonArrayMember(ContractVersionJson, { name: 'versions' })
public versions: ContractVersionJson[];

@jsonArrayMember(DisabledVersionJson, { name: 'disabled_versions' })
public disabledVersions: DisabledVersionJson[];

@jsonArrayMember(GroupsJson, { name: 'groups' })
public groups: GroupsJson[];
}

@jsonObject
export class StoredValue {
// StoredVale
@jsonMember({ constructor: CLValue })
@jsonMember({
name: 'CLValue',
deserializer: json => {
if (!json) return;
return CLValueParsers.fromJSON(json).unwrap();
}
})
public CLValue?: CLValue;

// An account
@jsonMember({ constructor: AccountJson })
public Account?: AccountJson;
Expand All @@ -186,8 +301,8 @@ export class StoredValue {
public Contract?: ContractMetadataJson;

// A contract definition, metadata, and security container
@jsonMember({ constructor: String })
public ContractPackage?: string;
@jsonMember({ constructor: ContractPackageJson })
public ContractPackage?: ContractPackageJson;

// A record of a transfer
@jsonMember({ constructor: TransferJson })
Expand Down
92 changes: 91 additions & 1 deletion src/services/CasperServiceByJsonRPC.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { RequestManager, HTTPTransport, Client } from '@open-rpc/client-js';
import { jsonMember, jsonObject } from 'typedjson';
import { DeployUtil, encodeBase16, CLPublicKey } from '..';
import { deployToJson } from '../lib/DeployUtil';
import { TypedJSON } from 'typedjson';
import { StoredValue } from '../lib/StoredValue';
import { StoredValue, Transfers } from '../lib/StoredValue';
import { BigNumber } from '@ethersproject/bignumber';

interface RpcResult {
Expand Down Expand Up @@ -123,6 +124,21 @@ export interface ValidatorWeight {
weight: string;
}

@jsonObject
export class EraSummary {
@jsonMember({ constructor: String, name: 'block_hash' })
blockHash: string;

@jsonMember({ constructor: Number, name: 'era_id' })
eraId: number;

@jsonMember({ constructor: StoredValue, name: 'stored_value' })
StoredValue: StoredValue;

@jsonMember({ constructor: String, name: 'state_root_hash' })
stateRootHash: string;
}

export interface EraValidators {
era_id: number;
validator_weights: ValidatorWeight[];
Expand Down Expand Up @@ -354,4 +370,78 @@ export class CasperServiceByJsonRPC {
params: deployToJson(signedDeploy)
});
}

/**
* Retrieves all transfers for a block from the network
* @param blockIdentifier Hex-encoded block hash or height of the block. If not given, the last block added to the chain as known at the given node will be used. If not provided it will retrieve by latest block.
*/
public async getBlockTransfers(blockHash?: string): Promise<Transfers> {
const res = await this.client.request({
method: 'chain_get_block_transfers',
params: {
block_identifier: blockHash
? {
Hash: blockHash
}
: null
}
});
if (res.error) {
return res;
} else {
const serializer = new TypedJSON(Transfers);
const storedValue = serializer.parse(res)!;
return storedValue;
}
}

/**
* Retrieve era information by block hash.
* @param blockIdentifier Hex-encoded block hash or height of the block. If not given, the last block added to the chain as known at the given node will be used. If not provided it will retrieve by latest block.
*/
public async getEraInfoBySwitchBlock(
blockHash?: string
): Promise<EraSummary> {
const res = await this.client.request({
method: 'chain_get_era_info_by_switch_block',
params: {
block_identifier: blockHash
? {
Hash: blockHash
}
: null
}
});
if (res.error) {
return res;
} else {
const serializer = new TypedJSON(EraSummary);
const storedValue = serializer.parse(res.era_summary)!;
return storedValue;
}
}

/**
* Retrieve era information by block height
* @param blockHeight
*/
public async getEraInfoBySwitchBlockHeight(
height: number
): Promise<EraSummary> {
const res = await this.client.request({
method: 'chain_get_era_info_by_switch_block',
params: {
block_identifier: {
Height: height
}
}
});
if (res.error) {
return res;
} else {
const serializer = new TypedJSON(EraSummary);
const storedValue = serializer.parse(res.era_summary)!;
return storedValue;
}
}
}
12 changes: 0 additions & 12 deletions test/lib/StoredValue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,6 @@ describe('StoredValue', () => {
);
});

it('should parse ContractPackage stored value correctly', function () {
const mockJson = {
ContractPackage:
'9eab12b986299509b4471060fe4d17f087bdd2596871c38d39019ef94f8d10a6070100000001000000010000001c16234ad1d27b51614ec5dca0bc28ea235eb2dc3a1f9d98aa238dc3df1fd63a0000000000000000'
};

const serializer = new TypedJSON(StoredValue);
const storedValue = serializer.parse(mockJson);
expect(storedValue?.ContractPackage).to.not.eq(undefined);
expect(storedValue?.ContractPackage).to.eq(mockJson.ContractPackage);
});

it('should parse DeployInfo stored value correctly', function () {
const mockJson = {
DeployInfo: {
Expand Down
Loading

0 comments on commit 3056131

Please sign in to comment.