A library for interacting with the contract phat-quickjs
The available JS APIs can be found here.
Script args and return value
The eval_* functions take a script as source code and args as input. It eval the source by delegate call to the code pointed to by
driver JsDelegate2 and return the value of the js expresson. The return value only lost-less supports string or Uint8Array. Ojbects
of other types will be casted to string.
Example:
let src = r#"
(function () {
return scriptArgs[0] + scriptArgs[1];
})()
"#;
let output = phat_js::eval(src, &["foo".into(), "bar".into()]);
assert_eq!(output, Ok(phat_js::Output::String("foobar".into())));
JS API examples
Cross-contract call
// Delegate calling
const delegateOutput = pink.;
// Instance calling
const contractOutput = pink.;
HTTP request
HTTP request is supported in the JS environment. However, the API is sync rather than async. This is different from other JavaScript engines. For example:
const response = pink.;
console.log;
SCALE codec
Let's introduce the details of the SCALE codec API which is not documented in the above link.
The SCALE codec API is mounted on the global object pink.SCALE which contains the following functions:
pink.SCALE.parseTypes(types: string): TypeRegistrypink.SCALE.codec(type: string | number | number[], typeRegistry?: TypeRegistry): Codec
Let's make a basice example to show how to use the SCALE codec API:
const types = `
Hash=[u8;32]
Info={hash:Hash,size:u32}
`;
const typeRegistry = pink.;
const infoCodec = pink.;
const encoded = infoCodec.;
console.log;
const decoded = infoCodec.;
pink.;
The above code will output:
JS: encoded: 18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18,52,86,120,144,18,52,210,4,0,0
JS: decoded: {
JS: hash: 0x1234567890123456789012345678901234567890123456789012345678901234,
JS: size: 1234
JS: }
Grammar of the type definition
Basic grammar
In the above example, we use the following type definition:
Hash=[u8;32]
Info={hash:Hash,size:u32}
where we define a type Hash which is an array of 32 bytes, and a type Info which is a struct containing a Hash and a u32.
The grammar is defined as follows:
Each entry is type definition, which is of the form name=type. Then name must be a valid identifier,
and type is a valid type expression described below.
Type expression can be one of the following:
| Type Expression | Description | Example |
|---|---|---|
#-prefixed |
Primitive types. | #bool, #u8, #u16, #u32, #u64, #u128, #i8, #i16, #i32, #i64, #i128, #str |
[type;size] |
Array type with element type type and size size. |
[#u8; 32] |
(type1, type2, ...) |
Tuple type with elements of type type1, type2, ... |
(#u8, #str) |
{field1:type1, field2:type2, ...} |
Struct type with fields and types. | {age:#u32, name:#str} |
<variant1:type1, variant2:type2, ...> |
Enum type with variants and types. if the variant is a unit variant, then the type expression can be omitted. | <Success:#i32, Error:#str>, <Some:#u32,None> |
Nested type definition
Type definition can be nested, for example:
Block={header:{hash:[u8;32],size:u32}}
Generic type support
Generic parameters can be added to the type definition, for example:
Result<T,E>=<Ok:T,Err:E>
Direct encode/decode API
The encode/decode api also support literal type definition as well as a typename or id, for example:
const data = ;
const encoded = pink.;
const decoded = pink.;
Error handling
Host calls would throw an exception if any error is encountered. For example, if we pass an invalid method to the API:
try catch