casper-ecosystem / casper-js-sdk

TypeScript Casper Client SDK
Apache License 2.0
71 stars 60 forks source link

Cannot Build CLKey from Contract Hash #327

Closed dylanireland closed 3 months ago

dylanireland commented 1 year ago

Using the casper-client, it is possible to give any hash value the type key, but the Casper JS SDK lacks the ability to build a CLKey object from any given hash.

For example, on line 7 in this shell script, a key argument is defined with the value "hash-b62481085812c4f56027f5fb7f3e5e2f087b14190da8762fb88889e4945178be". This works properly. Here is a successful deploy as an example (expand the raw data and look under the first argument contract_hash).

Using the Casper JS SDK, however, it appears this cannot be done.

Traditionally, building a CLKey object is done by calling CLValueBuilder.key(), which accepts a parameter of type CLKeyParameters, which is any of the following types:

Reference: CLKey, CLValueBuilder.key, CLKeyParameters.

Converting the contract hash string above into any of these four types, and then into a CLKey using CLValueBuilder.key(CLKeyParameters) yields different errors, from the inability to unpack the deploy in the Casper Wallet to empty arguments when deployed.

Here is my attempted implementation.

My proposed solution is creating a new class CLContractHash and conforming it to CLKeyParameters.

andrzej-casper commented 1 year ago

Just looking how CLKey is parsed for contract hash:

https://github.com/casper-ecosystem/casper-js-sdk/blob/e217c4b0e6cb65f60d19db0ae1c25150d2cd2d00/src/lib/CLValue/Key.ts#L49-L57

The idea is that regular byte array is prefixed with variant byte.

So as a workaround we can do it manually:

import { KeyVariant, CLByteArray, CLValueBuilder } from "casper-js-sdk";
import { concat } from '@ethersproject/bytes';

const contractHash = "cb781f66f78a398bf1709c4dac40b3cca17106824ea88ca9daa5b822421c9b57";
const clContractHash = new CLByteArray(
    concat([
        Uint8Array.from([KeyVariant.Hash]),
        Uint8Array.from(Buffer.from(contractHash, 'hex'))
    ])
);
const key = CLValueBuilder.key(clContractHash);

It works, but CLContractHash is definitely missing in the SDK.

dylanireland commented 1 year ago

Nice solution. In my case, adding Uint8Array.from([KeyVariant.Hash]) added another “01”. It appears to actually be as simple as:

const clContractHash = new CLByteArray(Uint8Array.from(Buffer.from(contractHash, "hex")));
const key = CLValueBuilder.key(clContractHash);

I had previously tried this, but was using TextEncoder instead of Buffer because I was in a React environment, and TextEncoder assumed the text was UTF-8 not hex. Instead, for React, one can actually just use decodeBase16 from Conversions like so:

import { decodeBase16, CLByteArray, CLValueBuilder } from "casper-js-sdk";

const contractHash = "cb781f66f78a398bf1709c4dac40b3cca17106824ea88ca9daa5b822421c9b57";
const clContractHash = new CLByteArray(decodeBase16(contractHash));
const key = CLValueBuilder.key(clContractHash);

Should still implement a CLContractHash though.

hoffmannjan commented 1 year ago

hey guys, yeah we will add CLContractHash in upcoming release !