nearprotocol / assemblyscript

A TypeScript to WebAssembly compiler 🚀
https://assemblyscript.org
Apache License 2.0
8 stars 1 forks source link

Fix endcoding/decoding of builtins #45

Closed willemneal closed 3 years ago

willemneal commented 5 years ago

E.g.

ERROR TS2339: Property 'encode' does not exist on type '~lib/string/String'.

               result.encode(encoder, null);
                      ~~~~~~
 in assembly/main.ts(108,21)
willemneal commented 5 years ago

Turns out it does handle strings. The issue was that when I changed the return type of an exported function to string | null then the wrapper no longer saw it as a string since "string" !== "string | null".

This was done because storage.get(key) returns a value or null. So the way I got it to compile was to add do return storage.get(key)! which turns into a runtime check and if the value returned is null it aborts.

The more I think about it the less I like the idea of return null, because internall null is the zero index into the function table, which means that the outside would will just see zero. So I think that it's fair to abort if the return value is null.

@bowenwang1996 @vgrichina Thoughts?

bowenwang1996 commented 5 years ago

Which function is this?

willemneal commented 5 years ago

main.ts from near-shell/blank_project:

//@nearfile
import { near, context, storage, logging } from "near-runtime-ts";
import { Greeter } from "./model";

// --- contract code goes below

// It's good to use common constant, but not required.
const LAST_SENDER_KEY = "last_sender";

// This is our change method. It modifies the state of the contract by
// storing the account_id of the sender under the key "last_sender" on the blockchain
export function sayHi(): void {
  // context.sender is the account_id of the user who sent this call to the contract
  // It's provided by the Blockchain runtime. For now we just store it in a local variable.
  let sender = context.sender;
  // `near` class contains some helper functions, e.g. logging.
  // Logs are not persistently stored on the blockchain, but produced by the blockchain runtime.
  // It's helpful to use logs for debugging your functions or when you need to get some info
  // from the change methods (since change methods don't return values to the front-end).
  logging.log(sender + " says \"Hello mate!\"");
  // storage is a helper class that allows contracts to modify the persistent state
  // and read from it. setString allows you to persitently store a string value for a given string key.
  // We'll store the last sender of this contract who called this method.
  storage.setString(LAST_SENDER_KEY, sender);
}

// This is our view method. It returns the last account_id of a sender who called `sayHi`.
// It reads value from the persistent store under the key "last_sender" and returns it.
export function whoSaidHi(): string {
  // getString returns a string value for a given string key.
  return storage.getString(LAST_SENDER_KEY)!;
}

It's the last function, which returns a string and now checks that the string from storage is not null at runtime.

bowenwang1996 commented 5 years ago

Yeah I think that's fine. The string should exist and if it does not then the program should abort.

willemneal commented 5 years ago

So should we push this into the storage class or should users have to add the !?

bowenwang1996 commented 5 years ago

Users should add !. The storage API is not subject to change at this point

github-actions[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in one week if no further activity occurs. Thank you for your contributions!