-
Notifications
You must be signed in to change notification settings - Fork 98
feat(userlib): Bump Motoko and support principal type in userlib #433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2f03416
90b3c67
513e760
0b723b9
098ac4d
1c364d3
eef4d6c
0e99523
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,17 @@ | ||
| // Canister IDs are represented as an array of bytes in the HTTP handler of the client. | ||
| export class CanisterId { | ||
| public static fromText(hex: string): CanisterId { | ||
| if (hex.startsWith('ic:')) { | ||
| // Remove the checksum from the hexadecimal. | ||
| // TODO: validate the checksum. | ||
| return this.fromHex(hex.slice(3, -2)); | ||
| public static fromText(text: string): CanisterId { | ||
| if (text.startsWith('ic:')) { | ||
| const hex = text.slice(3); | ||
| if (hex.length % 2 === 0 && /^[0-9A-F]+$/.test(hex)) { | ||
| // Remove the checksum from the hexadecimal. | ||
| // TODO: validate the checksum. | ||
| return this.fromHex(hex.slice(0, -2)); | ||
| } else { | ||
| throw new Error('Cannot parse canister id: ' + text); | ||
| } | ||
| } else { | ||
| throw new Error('CanisterId not a "ic:" url: ' + hex); | ||
| throw new Error('CanisterId not a "ic:" url: ' + text); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -19,4 +24,7 @@ export class CanisterId { | |
| public toHex(): string { | ||
| return this._idHex; | ||
| } | ||
| public toText(): string { | ||
| return 'ic:' + this.toHex() + '00'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t forget a |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| import BigNumber from 'bignumber.js'; | ||
| import Pipe = require('buffer-pipe'); | ||
| import { Buffer } from 'buffer/'; | ||
| import { CanisterId } from './canisterId'; | ||
| import { JsonValue } from './types'; | ||
| import { idlLabelToId } from './utils/hash'; | ||
| import { lebDecode, lebEncode, slebDecode, slebEncode } from './utils/leb128'; | ||
|
|
@@ -26,6 +27,9 @@ const enum IDLTypeIds { | |
| Vector = -19, | ||
| Record = -20, | ||
| Variant = -21, | ||
| Func = -22, | ||
| Service = -23, | ||
| Principal = -24, | ||
| } | ||
|
|
||
| const magicNumber = 'DIDL'; | ||
|
|
@@ -95,7 +99,7 @@ export abstract class Visitor<D, R> { | |
| public visitBool(t: BoolClass, data: D): R { | ||
| return this.visitPrimitive(t, data); | ||
| } | ||
| public visitUnit(t: UnitClass, data: D): R { | ||
| public visitNull(t: NullClass, data: D): R { | ||
| return this.visitPrimitive(t, data); | ||
| } | ||
| public visitText(t: TextClass, data: D): R { | ||
|
|
@@ -113,6 +117,9 @@ export abstract class Visitor<D, R> { | |
| public visitFixedNat(t: FixedNatClass, data: D): R { | ||
| return this.visitPrimitive(t, data); | ||
| } | ||
| public visitPrincipal(t: PrincipalClass, data: D): R { | ||
| return this.visitPrimitive(t, data); | ||
| } | ||
|
|
||
| public visitConstruct<T>(t: ConstructType<T>, data: D): R { | ||
| return this.visitType(t, data); | ||
|
|
@@ -265,9 +272,9 @@ export class BoolClass extends PrimitiveType<boolean> { | |
| /** | ||
| * Represents an IDL Null | ||
| */ | ||
| export class UnitClass extends PrimitiveType<null> { | ||
| export class NullClass extends PrimitiveType<null> { | ||
| public accept<D, R>(v: Visitor<D, R>, d: D): R { | ||
| return v.visitUnit(this, d); | ||
| return v.visitNull(this, d); | ||
| } | ||
|
|
||
| public covariant(x: any): x is null { | ||
|
|
@@ -873,7 +880,52 @@ export class RecClass<T = any> extends ConstructType<T> { | |
| } | ||
|
|
||
| /** | ||
| * Represents an async function which can return data. | ||
| * Represents an IDL principal reference | ||
| */ | ||
| export class PrincipalClass extends PrimitiveType<CanisterId> { | ||
| public accept<D, R>(v: Visitor<D, R>, d: D): R { | ||
| return v.visitPrincipal(this, d); | ||
| } | ||
|
|
||
| public covariant(x: any): x is CanisterId { | ||
| return x instanceof CanisterId; | ||
| } | ||
|
|
||
| public encodeValue(x: CanisterId): Buffer { | ||
| const hex = x.toHex(); | ||
| const buf = Buffer.from(hex, 'hex'); | ||
| const len = lebEncode(buf.length); | ||
| return Buffer.concat([Buffer.from([1]), len, buf]); | ||
| } | ||
|
|
||
| public encodeType() { | ||
| return slebEncode(IDLTypeIds.Principal); | ||
| } | ||
|
|
||
| public decodeValue(b: Pipe): CanisterId { | ||
| const x = b.read(1).toString('hex'); | ||
| if (x !== '01') { | ||
| throw new Error('Cannot decode principal'); | ||
| } | ||
| const len = lebDecode(b).toNumber(); | ||
| const hex = b | ||
| .read(len) | ||
| .toString('hex') | ||
| .toUpperCase(); | ||
| // TODO implement checksum | ||
| return CanisterId.fromText('ic:' + hex + '00'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sounds good, but perhaps we need to centralize all this in a IC identifier library?? I am going to add senders for instance which is more of the same logic. And this is canister id specific. (No change asked for this PR, just asking, as I want to do something similar.)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Same applies to Rust. canisterId is defined inside the ic_http_agent crate. Probably separate that out as well.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. I have been pondering that. Not sure which option is the best. |
||
| } | ||
|
|
||
| get name() { | ||
| return 'principal'; | ||
| } | ||
| public valueToString(x: CanisterId) { | ||
| return x.toText(); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Represents an IDL function reference. | ||
| * @param argTypes Argument types. | ||
| * @param retTypes Return types. | ||
| * @param annotations Function annotations. | ||
|
|
@@ -994,16 +1046,13 @@ export function decode(retTypes: Type[], bytes: Buffer): JsonValue[] { | |
| * @param {Object} [fields] - a map of function names to IDL function signatures | ||
| */ | ||
| export class ActorInterface { | ||
| protected _id: Blob | null = null; | ||
| protected _batch: boolean = false; | ||
|
|
||
| constructor(public _fields: Record<string, FuncClass>) {} | ||
| } | ||
|
|
||
| // Export Types instances. | ||
| export const Empty = new EmptyClass(); | ||
| export const Bool = new BoolClass(); | ||
| export const Unit = new UnitClass(); | ||
| export const Null = new NullClass(); | ||
| export const Text = new TextClass(); | ||
| export const Int = new IntClass(); | ||
| export const Nat = new NatClass(); | ||
|
|
@@ -1018,6 +1067,8 @@ export const Nat16 = new FixedNatClass(16); | |
| export const Nat32 = new FixedNatClass(32); | ||
| export const Nat64 = new FixedNatClass(64); | ||
|
|
||
| export const Principal = new PrincipalClass(); | ||
|
|
||
| export function Tuple<T extends any[]>(...types: T): TupleClass<T> { | ||
| return new TupleClass(types); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't fromHex fail here actually? (I thought it was failing.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fromHex just stores the string. It doesn't do any checks.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I can swear I had added checks in encode decode functions somewhere...
carry on 😉