Photo by Georgie Cobbs on Unsplash
To port our web editor, DeckDeckGo, to DFINITY’s Internet Computer I developed several helpers in TypeScript to interact with our canister smart contracts.
If it can make your life easier too, here are those I use the most.
Nullable
The Candid description that is generated for nullable types does not exactly match what I commonly used in JavaScript for optional types (see this post for the why and how).
For example, if we generate an interface for such a Motoko code snippet:
actor Example {
public shared query func list(filter: ?Text) : async [Text] {
let results: [Text] = myFunction(filter);
return results;
};
}
The definition of the optional parameter filter
will not be interpreted as a string
that can potentially be undefined
but, rather as a one-element length array
that contains a string
or is empty.
export interface _SERVICE {
list: (arg_0: [] | [string]) => Promise<Array<string>>;
}
That is why I created functions to convert back and forth optional values.
export const toNullable = <T>(value?: T): [] | [T] => {
return value ? [value] : [];
};
export const fromNullable = <T>(value: [] | [T]): T | undefined => {
return value?.[0];
};
toNullable
convert an object that can either be of type T
or undefined
to what’s expected to interact with the IC and, fromNullable
do the opposite.
Dates
System Time (nanoseconds since 1970–01–01) gets parsed to bigint
and exported as a type Time
in Candid definition.
export type Time = bigint;
To convert JavaScript Date
to big numbers, the built-in object BigInt can be instantiated by multiplying seconds to nano seconds.
export const toTimestamp = (value: Date): Time => {
return BigInt(value.getTime() * 1000 * 1000);
};
The other way around works by converting first the big numbers to their primitive Number types and dividing it to seconds.
export const fromTimestamp = (value: Time): Date => {
return new Date(Number(value) / (1000 * 1000));
};
To support Nullable
timestamps values, I also created the following helpers that extend above converters and return the appropriate optional arrays.
export const toNullableTimestamp = (value?: Date): [] | [Time] => {
const time: number | undefined = value?.getTime();
return value && !isNaN(time) ? [toTimestamp(value)] : [];
};
export const fromNullableTimestamp =
(value?: [] | [Time]): Date | undefined => {
return !isNaN(parseInt(`${value?.[0]}`)) ?
fromTimestamp(value[0]) : undefined;
};
Blob
Binary blobs are described in Candid as Array
of numbers
. To save untyped data in smart contracts (assuming the use case allows such risk) while still preserving types on the frontend side, we can stringify
objects, converts these to blobs and gets their contents as binary data contained in an ArrayBuffer
.
export const toArray =
async <T>(data: T): Promise<Array<number>> => {
const blob: Blob = new Blob([JSON.stringify(data)],
{type: 'application/json; charset=utf-8'});
return [...new Uint8Array(await blob.arrayBuffer())];
};
To convert back an Array
of numbers
to a specific object type, the Blob type can be used again but, this time a textual conversion shall be used to parse the results.
export const fromArray =
async <T>(data: Array<number>): Promise<T> => {
const blob: Blob = new Blob([new Uint8Array(data)],
{type: 'application/json; charset=utf-8'});
return JSON.parse(await blob.text());
};
Both conversions are asynchronous because interacting with the blob object requires resolving promises in JavaScript.
Further Reading
Wanna read more our project? Here is the list of blog posts I published since we started the project with the Internet Computer:
- Bye-Bye Amazon & Google, Hello Web 3.0
- Dynamically Import ESM Modules From A CDN
- Internet Computer: Web App Decentralized Database Architecture
- Singleton & Factory Patterns With TypeScript
- Hosting on the Internet Computer
- We Received A Grant To Port Our Web App To The Internet Computer
Keep In Touch
To follow our adventure, you can star and watch our GitHub repo ⭐️ and sign up to join the list of beta tester.
Conclusion
I hope this short blog post and few utilities will be useful for you to start well with the Internet Computer, it is really a fun technology.
To infinity and beyond!
David