diff --git a/assembly/env/env.ts b/assembly/env/env.ts index 1d40445a..3181ab2a 100644 --- a/assembly/env/env.ts +++ b/assembly/env/env.ts @@ -225,4 +225,28 @@ export namespace env { @external("massa", "assembly_script_chain_id") export declare function chainId(): u64; + + @external("massa", "assembly_script_deferred_call_quote") + export declare function deferredCallQuote( + ascPeriod: u64, + ascThread: u8, + maxGas: u64, + ): u64; + + @external("massa", "assembly_script_deferred_call_register") + export declare function deferredCallRegister( + targetAddress: string, + targetFunction: string, + targetPeriod: u64, + targetThread: u8, + maxGas: u64, + params: StaticArray, + rawCoins: u64, + ): string; + + @external("massa", "assembly_script_deferred_call_exists") + export declare function deferredCallExists(callId: string): bool; + + @external("massa", "assembly_script_deferred_call_cancel") + export declare function deferredCallCancel(callId: string): void; } diff --git a/assembly/std/context.ts b/assembly/std/context.ts index 19a1444a..ecfa93fe 100644 --- a/assembly/std/context.ts +++ b/assembly/std/context.ts @@ -201,3 +201,12 @@ export function currentThread(): u8 { export function chainId(): u64 { return env.chainId(); } + +export class Slot { + public period: u64; + public thread: u8; + public constructor(period: u64, thread: u8) { + this.period = period; + this.thread = thread; + } +} diff --git a/assembly/std/deferredCalls.ts b/assembly/std/deferredCalls.ts new file mode 100644 index 00000000..8ed3445c --- /dev/null +++ b/assembly/std/deferredCalls.ts @@ -0,0 +1,107 @@ +/** + * This module contains all the functions to interact with Massa deferred call (Garanted Autonomous Smart Contracts) + */ + +import { env } from '../env'; +import { Slot } from './context'; + +/** + * Get the price of booking a deferred call in a given slot. + * + * @param targetSlot - The targeted slot + * @param maxGas - The maximum amount of gas that the deferred call can use + * + * @returns Mas amount + * + */ +export function deferredCallQuote(targetSlot: Slot, maxGas: u64): u64 { + return env.deferredCallQuote(targetSlot.period, targetSlot.thread, maxGas); +} + +/** + * Register a new deferred call + * + * @param targetAddress - The address of the target deferred call + * @param targetFunction - The function to call in the target deferred call + * @param targetSlot - The target slot for the deferred call + * @param maxGas - The maximum amount of gas that the deferred call can use + * @param params - The parameters to send to the target deferred call function + * @param rawCoins - The amount of coins to send to the target deferred call + * + * @returns The id of the new deferred call + */ +export function deferredCallRegister( + targetAddress: string, + targetFunction: string, + targetSlot: Slot, + maxGas: u64, + params: StaticArray, + rawCoins: u64, +): string { + return env.deferredCallRegister( + targetAddress, + targetFunction, + targetSlot.period, + targetSlot.thread, + maxGas, + params, + rawCoins, + ); +} + +/** + * Check if an deferred call exists + * + * @param ascCallId - The id of the deferred call + * + * @returns True if the deferred call exists otherwise false + */ +export function deferredCallExists(ascCallId: string): bool { + return env.deferredCallExists(ascCallId); +} + +/** + * Cancel an deferred call + * + * @param ascCallId - The id of the deferred call + * + * @returns True if the deferred call has been canceled otherwise false + */ +export function deferredCallCancel(ascCallId: string): void { + env.deferredCallCancel(ascCallId); +} + +/** + * Find the cheapest slot within a given period range. + * + * @param startPeriod - The start period of the range to check + * @param endPeriod - The end period of the range to check + * @param maxGas - The maximum amount of gas that the deferred call can use + * + * @returns An object containing the period and thread of the cheapest slot + */ +export function findCheapestSlot( + startPeriod: u64, + endPeriod: u64, + maxGas: u64, +): Slot { + let cheapestSlotPeriod: u64 = startPeriod; + let cheapestSlotThread: u8 = 0; + let cheapestSlotPrice: u64 = deferredCallQuote( + new Slot(startPeriod, 0), + maxGas, + ); + + for (let period = startPeriod; period <= endPeriod; period++) { + for (let thread: u8 = 1; thread < 32; thread++) { + const price = deferredCallQuote(new Slot( period, thread ), maxGas); + if (price < cheapestSlotPrice) { + cheapestSlotPrice = price; + cheapestSlotPeriod = period; + cheapestSlotThread = thread; + } + } + } + + return new Slot(cheapestSlotPeriod, cheapestSlotThread); +} diff --git a/assembly/std/index.ts b/assembly/std/index.ts index 1e495153..caba1626 100644 --- a/assembly/std/index.ts +++ b/assembly/std/index.ts @@ -51,3 +51,8 @@ export * from './context'; * @module Storage */ export * from './storage'; + +/** + * @module DeferredCalls + */ +export * from './deferredCalls';