Returning type of an async inline function to another actor

Let’s say that I want a function that makes an async call and returns a future (that can be awaited upon.

  type LedgerActor = actor {
    icrc1_balance_of : ({owner: Principal; subaccount: ?Blob}) -> async Nat;
  };

  func makeBalanceOfFuture(ledgerActor: LedgerActor, owner : Principal) : async Nat {
    ledgerActor.icrc1_balance_of({ owner; subaccount = null });
  };

I’d like to be able to do this, but the compiler yells:

expression of type
  async<$makeBalanceOfFuture> Nat
cannot produce expected type
  Nat (M0096)

Using async<$makeBalanceOfFuture> Nat isn’t supported

// Not supported
func makeBalanceOfFuture(ledgerActor: LedgerActor, owner : Principal) : async<$makeBalanceOfFuture> Nat

I tried a number of approaches to what the type of $makeBalanceOfFuture could be, but gave up and figured it would be easier to just ask in the forums.

Is it possible in Motoko to achieve what I’m trying to do here? :sweat_smile:

The magic scope parameter on the async type isn’t really relevant to the message, the mismatch is between Nat and async Nat. That is, you’re missing an await.

The async body of makeBalance already wraps a future around its result, so to produce an async Nat, its contents must produce a plain Nat. If you have an async Nat there, then you need to await it first to produce such a Nat.

Unfortunately, that means that an async function cannot directly return the future received from another call. Semantically, you’d expect that should be possible, but the limitations of the IC’s underlying architecture get in the way of compiling such an abstraction.