From bf01489b335c2870c26b1b4687a0c0ee01a0059c Mon Sep 17 00:00:00 2001 From: Benjamin DeMann Date: Tue, 3 Oct 2023 14:57:29 -0600 Subject: [PATCH] fix typing for ic object --- src/lib/globals.ts | 11 ++- src/lib/ic/call.ts | 2 +- src/lib/ic/call128.ts | 2 +- src/lib/ic/call_raw.ts | 16 ++--- src/lib/ic/call_raw_128.ts | 16 ++--- src/lib/ic/clear_timer.ts | 2 +- src/lib/ic/data_certificate.ts | 3 +- src/lib/ic/notify.ts | 2 +- src/lib/ic/set_timer.ts | 4 +- src/lib/ic/set_timer_interval.ts | 2 +- src/lib/ic/types/azle_ic.ts | 90 +++++++++++++++++++++++++ src/lib/ic/{types.ts => types/index.ts} | 2 +- 12 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 src/lib/ic/types/azle_ic.ts rename src/lib/ic/{types.ts => types/index.ts} (89%) diff --git a/src/lib/globals.ts b/src/lib/globals.ts index afabb8c825..c94b92d5bd 100644 --- a/src/lib/globals.ts +++ b/src/lib/globals.ts @@ -1,10 +1,17 @@ -import { Ic, ic } from './ic'; +import { ic } from './ic'; +import { AzleIc } from './ic/types/azle_ic'; import { Buffer } from 'buffer'; declare global { - var _azleIc: Ic; + var _azleIc: AzleIc; + var _azleResolveIds: { [key: string]: (buf: ArrayBuffer) => void }; + var _azleRejectIds: { [key: string]: (err: any) => void }; + var icTimers: { [key: string]: string }; + var _azleTimerCallbackIds: { [key: string]: () => void }; } +interface global {} + export declare var globalThis: { _azleCandidInitParams: any[]; _azleCandidMethods: any[]; diff --git a/src/lib/ic/call.ts b/src/lib/ic/call.ts index e036667026..dcd58ab960 100644 --- a/src/lib/ic/call.ts +++ b/src/lib/ic/call.ts @@ -20,7 +20,7 @@ export function call any>( } ): ReturnTypeOf { // TODO probably get rid of .crossCanisterCallback - return method.crossCanisterCallback( + return (method as any).crossCanisterCallback( '_AZLE_CROSS_CANISTER_CALL', false, callRaw, diff --git a/src/lib/ic/call128.ts b/src/lib/ic/call128.ts index c2d0a1c419..da7d509f50 100644 --- a/src/lib/ic/call128.ts +++ b/src/lib/ic/call128.ts @@ -19,7 +19,7 @@ export function call128 any>( cycles?: nat; } ): ReturnTypeOf { - return method.crossCanisterCallback( + return (method as any).crossCanisterCallback( '_AZLE_CROSS_CANISTER_CALL', false, callRaw128, diff --git a/src/lib/ic/call_raw.ts b/src/lib/ic/call_raw.ts index 81bf6152a1..84437de527 100644 --- a/src/lib/ic/call_raw.ts +++ b/src/lib/ic/call_raw.ts @@ -30,18 +30,18 @@ export function callRaw( // TODO perhaps we should be more robust // TODO for example, we can keep the time with these // TODO if they are over a certain amount old we can delete them - globalThis[globalResolveId] = (bytes: ArrayBuffer) => { + globalThis._azleResolveIds[globalResolveId] = (bytes: ArrayBuffer) => { resolve(new Uint8Array(bytes)); - delete globalThis[globalResolveId]; - delete globalThis[globalRejectId]; + delete globalThis._azleResolveIds[globalResolveId]; + delete globalThis._azleRejectIds[globalRejectId]; }; - globalThis[globalRejectId] = (error: any) => { + globalThis._azleRejectIds[globalRejectId] = (error: any) => { reject(error); - delete globalThis[globalResolveId]; - delete globalThis[globalRejectId]; + delete globalThis._azleResolveIds[globalResolveId]; + delete globalThis._azleRejectIds[globalRejectId]; }; const canisterIdBytes = canisterId.toUint8Array().buffer; @@ -60,8 +60,8 @@ export function callRaw( paymentCandidBytes ); } catch (error) { - delete globalThis[globalResolveId]; - delete globalThis[globalRejectId]; + delete globalThis._azleResolveIds[globalResolveId]; + delete globalThis._azleRejectIds[globalRejectId]; throw error; } }); diff --git a/src/lib/ic/call_raw_128.ts b/src/lib/ic/call_raw_128.ts index 19d3257c8e..80d6b0d3d8 100644 --- a/src/lib/ic/call_raw_128.ts +++ b/src/lib/ic/call_raw_128.ts @@ -30,18 +30,18 @@ export function callRaw128( // TODO perhaps we should be more robust // TODO for example, we can keep the time with these // TODO if they are over a certain amount old we can delete them - globalThis[globalResolveId] = (bytes: ArrayBuffer) => { + globalThis._azleResolveIds[globalResolveId] = (bytes: ArrayBuffer) => { resolve(new Uint8Array(bytes)); - delete globalThis[globalResolveId]; - delete globalThis[globalRejectId]; + delete globalThis._azleResolveIds[globalResolveId]; + delete globalThis._azleRejectIds[globalRejectId]; }; - globalThis[globalRejectId] = (error: any) => { + globalThis._azleRejectIds[globalRejectId] = (error: any) => { reject(error); - delete globalThis[globalResolveId]; - delete globalThis[globalRejectId]; + delete globalThis._azleResolveIds[globalResolveId]; + delete globalThis._azleRejectIds[globalRejectId]; }; const canisterIdBytes = canisterId.toUint8Array().buffer; @@ -60,8 +60,8 @@ export function callRaw128( paymentCandidBytes ); } catch (error) { - delete globalThis[globalResolveId]; - delete globalThis[globalRejectId]; + delete globalThis._azleResolveIds[globalResolveId]; + delete globalThis._azleRejectIds[globalRejectId]; throw error; } }); diff --git a/src/lib/ic/clear_timer.ts b/src/lib/ic/clear_timer.ts index f6b937200e..b329b6af53 100644 --- a/src/lib/ic/clear_timer.ts +++ b/src/lib/ic/clear_timer.ts @@ -16,5 +16,5 @@ export function clearTimer(timerId: TimerId): Void { const timerCallbackId = globalThis.icTimers[timerId.toString()]; delete globalThis.icTimers[timerId.toString()]; - delete globalThis[timerCallbackId]; + delete globalThis._azleTimerCallbackIds[timerCallbackId]; } diff --git a/src/lib/ic/data_certificate.ts b/src/lib/ic/data_certificate.ts index 1e27904962..5a3ba70d84 100644 --- a/src/lib/ic/data_certificate.ts +++ b/src/lib/ic/data_certificate.ts @@ -8,8 +8,7 @@ import { None, Opt, Some } from '../candid/types/constructed/opt'; * @returns the data certificate or None */ export function dataCertificate(): Opt { - const rawRustValue: ArrayBuffer | undefined = - globalThis._azleIc.dataCertificate(); + const rawRustValue = globalThis._azleIc.dataCertificate(); return rawRustValue === undefined ? None diff --git a/src/lib/ic/notify.ts b/src/lib/ic/notify.ts index 18be210fc2..d033558fca 100644 --- a/src/lib/ic/notify.ts +++ b/src/lib/ic/notify.ts @@ -39,7 +39,7 @@ export function notify any>( cycles?: nat; } ): Void { - return method.crossCanisterCallback( + return (method as any).crossCanisterCallback( '_AZLE_CROSS_CANISTER_CALL', true, notifyRaw, diff --git a/src/lib/ic/set_timer.ts b/src/lib/ic/set_timer.ts index dd75ea3789..405fa159c3 100644 --- a/src/lib/ic/set_timer.ts +++ b/src/lib/ic/set_timer.ts @@ -31,12 +31,12 @@ export function setTimer( globalThis.icTimers[timerId.toString()] = timerCallbackId; - globalThis[timerCallbackId] = () => { + globalThis._azleTimerCallbackIds[timerCallbackId] = () => { try { callback(); } finally { delete globalThis.icTimers[timerId.toString()]; - delete globalThis[timerCallbackId]; + delete globalThis._azleTimerCallbackIds[timerCallbackId]; } }; diff --git a/src/lib/ic/set_timer_interval.ts b/src/lib/ic/set_timer_interval.ts index bb9a8856d8..7965b5a9f3 100644 --- a/src/lib/ic/set_timer_interval.ts +++ b/src/lib/ic/set_timer_interval.ts @@ -33,7 +33,7 @@ export function setTimerInterval( // We don't delete this even if the callback throws because // it still needs to be here for the next tick - globalThis[timerCallbackId] = callback; + globalThis._azleTimerCallbackIds[timerCallbackId] = callback; return timerId; } diff --git a/src/lib/ic/types/azle_ic.ts b/src/lib/ic/types/azle_ic.ts new file mode 100644 index 0000000000..e9a752b554 --- /dev/null +++ b/src/lib/ic/types/azle_ic.ts @@ -0,0 +1,90 @@ +// This unverified signature is helpful for catching where we use this so we can pick up the types easily. If I do any then i will miss them all +type UnverifiedSignature = () => void; +/** + * The interface for our rust methods it slightly different than the interface + * we expose to the users. This is the interface for the rust functions. + */ +export type AzleIc = { + argDataRaw: () => ArrayBufferLike; + argDataRawSize: () => bigint; + callRaw: ( + promiseId: string, + canisterIdBytes: ArrayBufferLike, + method: string, + argsRaw: ArrayBufferLike, + paymentCandidBytes: ArrayBufferLike + ) => void; + callRaw128: ( + promiseId: string, + canisterIdBytes: ArrayBufferLike, + method: string, + argsRaw: ArrayBufferLike, + paymentCandidBytes: ArrayBufferLike + ) => void; + caller: () => ArrayBufferLike; + candidDecode: (candidBytes: ArrayBufferLike) => string; + candidEncode: (candidString: string) => ArrayBufferLike; + canisterBalance: () => ArrayBufferLike; + canisterBalance128: () => ArrayBufferLike; + canisterVersion: () => ArrayBufferLike; + clearTimer: (timerIdBytes: ArrayBufferLike) => void; + dataCertificate: () => ArrayBufferLike | undefined; + id: () => string; + instructionCounter: () => ArrayBufferLike; + isController: (principalBytes: ArrayBufferLike) => boolean; + msgCyclesAccept: (maxAmountCandidBytes: ArrayBufferLike) => ArrayBufferLike; + msgCyclesAccept128: ( + maxAmountCandidBytes: ArrayBufferLike + ) => ArrayBufferLike; + msgCyclesAvailable: () => ArrayBufferLike; + msgCyclesAvailable128: () => ArrayBufferLike; + msgCyclesRefunded: () => ArrayBufferLike; + msgCyclesRefunded128: () => ArrayBufferLike; + notifyRaw: ( + canisterIdBytes: ArrayBufferLike, + method: string, + argsRawBuffer: ArrayBufferLike, + paymentCandidBytes: ArrayBufferLike + ) => void; + performanceCounter: ( + counterTypeCandidBytes: ArrayBufferLike + ) => ArrayBufferLike; + rejectCode: () => number; + replyRaw: (bytes: ArrayBufferLike) => void; + setCertifiedData: (dataBytes: ArrayBufferLike) => void; + setTimer: ( + delayBytes: ArrayBufferLike, + timerCallbackId: string + ) => ArrayBufferLike; + setTimerInterval: ( + intervalBytes: ArrayBufferLike, + timerCallbackId: string + ) => ArrayBufferLike; + stableBytes: () => ArrayBufferLike; + stableGrow: (newPagesCandidBytes: ArrayBufferLike) => ArrayBufferLike; + stableRead: (paramsCandidBytes: ArrayBufferLike) => ArrayBufferLike; + stableSize: () => ArrayBufferLike; + stableWrite: (paramsCandidBytes: ArrayBufferLike) => void; + stable64Grow: (newPagesCandidBytes: ArrayBufferLike) => ArrayBufferLike; + stable64Read: (paramsCandidBytes: ArrayBufferLike) => ArrayBufferLike; + stable64Size: () => ArrayBufferLike; + stable64Write: (paramsCandidBytes: ArrayBufferLike) => void; + time: () => ArrayBufferLike; + // These calls aren't intercepted by our IC object, they go right to the + // rust version and come out. Since they don't need to be intercepted I am + // assuming that their types are the same as the types declared by out + // interceptor. + acceptMessage: () => void; + methodName: () => string; + print: (...args: any) => void; + reject: (message: string) => void; + rejectMessage: () => string; + trap: (message: string) => never; + // These calls are intercepted by our IC object and redirected to their + // corresponding raw version. The rust version is never called, we don't + // have enough info about types to do so + call: () => never; + call128: () => never; + notify: () => never; + reply: () => never; +}; diff --git a/src/lib/ic/types.ts b/src/lib/ic/types/index.ts similarity index 89% rename from src/lib/ic/types.ts rename to src/lib/ic/types/index.ts index 670868d4cd..fd3cf50ac9 100644 --- a/src/lib/ic/types.ts +++ b/src/lib/ic/types/index.ts @@ -1,4 +1,4 @@ -import { nat64, AzleNat64 } from '../candid/types/primitive/nats/nat64'; +import { nat64, AzleNat64 } from '../../candid/types/primitive/nats/nat64'; export type ArgsType = T extends (...args: infer U) => any ? U : any; export type ReturnTypeOf = T extends (...args: any[]) => infer R ? R : any;