From 7ff239a44e160e2b3ef069d854c19a5173335fc1 Mon Sep 17 00:00:00 2001
From: Bo Yao
Date: Wed, 1 Jun 2022 16:31:24 +0800
Subject: [PATCH 1/7] Update readme to reflect recent changes
---
README.md | 274 +++++++++++-------------------------------------------
1 file changed, 52 insertions(+), 222 deletions(-)
diff --git a/README.md b/README.md
index 3107687e9..9141b212d 100644
--- a/README.md
+++ b/README.md
@@ -1,283 +1,113 @@
-## Disclaimer:
-This README is a work in progress. The best way to start using `near-sdk-js` is to check `./examples`.
# NEAR-SDK-JS (Enclave)
-## Local Installation
-It is tested on Ubuntu 20.04 and Intel Mac. Other linux and M1 Macs should also work but they're not tested.
+## Getting started with template project
-1. Make sure you have `wget`, `make`, `cmake` and `nodejs`. On Linux, also make sure you have `gcc`.
-2. Run `make` to get platform specific `qjsc` and `jsvm` contract in `res` folder.
+The fastest and recommended way to develop with near-sdk-js is to create a project with our github template: https://github.com/near/near-sdk-js-template-project.
-## Usage
-1. `cd examples/`
-2. `yarn && yarn build` to get .base64 file (JS smart-contract).
-3. Use near-cli to deploy `jsvm.wasm` from the `res` folder to your account.
-4. Deploy .base64 file to `JSVM` account from the previous step.
-```sh
-near js deploy --accountId --base64File .base64 --deposit 0.1 --jsvm
-```
-
-Or use the raw CLI call instead
-
+## Running examples
- near call deploy_js_contract --accountId --args $(cat .base64) --base64 --deposit 0.1
+There are a couple of contract examples in the project:
-
-
+- [Clean contract state](https://github.com/near/near-sdk-js/tree/master/examples/clean-state)
+- [Doing cross contract call](https://github.com/near/near-sdk-js/tree/master/examples/cross-contract-call)
+- [Fungible token](https://github.com/near/near-sdk-js/tree/master/examples/fungible-token)
+- [Lockable fungible token](https://github.com/near/near-sdk-js/tree/master/examples/lockable-fungible-token)
+- [Non fungible token](https://github.com/near/near-sdk-js/tree/master/examples/non-fungible-token)
+- [Status message board](https://github.com/near/near-sdk-js/tree/master/examples/status-message)
+- [Status message board with search](https://github.com/near/near-sdk-js/tree/master/examples/status-message-collections)
-5. Interact with your contract using NEAR CLI or `near-api-js`. Encode the parameters and call. If the call cause the state increasement, you also need to attach NEAR to cover the storage deposit for the delta.
+The general steps to run these contracts are same. You can also try them by following their corresponding READMEs.
+### General steps to run examples locally
+1. Use near-cli to deploy `jsvm.wasm` from the `res` folder to one of account you controlled. For example, `jsvm.`:
```sh
-near js call --args --deposit 0.1 --jsvm
-```
-
-
-Or use the raw CLI call instead
-
-
- near call call_js_contract --accountId --args --base64
-
- # where `` can be obtained by:
- node encode_call.js
-
-
-
-
-6. If you want to remove the js contract and withdraw the storage deposit, use:
-
-```sh
-near js remove --accountId --jsvm
-```
-
-
-Or use the raw CLI call instead
-
-
- near call remove_js_contract --accountId
-
-
-
-
-## Demo
-
-### On a local node
-
-1. Build the jsvm contract
-```
-make
-```
-
-2. Go to nearcore, Build and start a local node
-```
-cargo build -p neard
-target/debug/neard init
-target/debug/neard run
+export NEAR_ENV=local
+near deploy res/jsvm.wasm
```
-
-3. Go back to `near-sdk-js`. Have `near-cli` installed. Deploy the jsvm contract. Example session:
+2. `cd examples/`
+3. `yarn && yarn build` to get .base64 file (JS smart-contract).
+4. Deploy .base64 file to `JSVM` account from the previous step.
```sh
-near-sdk-js (master) export NEAR_ENV=local
-near-sdk-js (master) near deploy test.near jsvm.wasm
+near js deploy --accountId --base64File build/.base64 --deposit 0.1 --jsvm
```
-
-Example output
-
-
- Loaded master account test.near key from /home/bo/.near/validator_key.json with public key = ed25519:XXqxAHP1ZRcwCwBTr1MbdF9NM7UVynuTnxhZfFeE5UJ
- Starting deployment. Account id: test.near, node: http://localhost:3030, helper: http://localhost:3000, file: jsvm.wasm
- Transaction Id EGVd29tthMp7fqkDgP8frftgZhhb3FVazaFhvXpYXNhw
- To see the transaction in the transaction explorer, please open this url in your browser
- http://localhost:9001/transactions/EGVd29tthMp7fqkDgP8frftgZhhb3FVazaFhvXpYXNhw
- Done deploying to test.near
-
-
-
+5. Interact with your contract using NEAR CLI or `near-api-js`. Encode the parameters and call. If the call cause the state increasement, you also need to attach NEAR to cover the storage deposit for the delta.
-4. Build, deploy hello contract to jsvm contract, and call hello. Example session:
```sh
-near-sdk-js (master) ./builder.sh examples/low-level/hello_near.js
-near-sdk-js (master) near js deploy --accountId test.near --base64 hello_near.base64 --deposit 0.1 --jsvm test.near
+near js call --args --deposit 0.1 --jsvm
```
-
-Or use the raw CLI call instead
-
-
- near-sdk-js (master) near call test.near deploy_js_contract --accountId test.near --base64 --args $(cat hello_near.base64) --deposit 0.1
-
-
-
-
-
-
-Example output
-
-
- Scheduling a call: test.near.deploy_js_contract(AgYsZXhhbXBsZXMvaGVsbG9fbmVhci5qcwpoZWxsbwxoZWxsbzIGZW52BmxvZxRIZWxsbyBOZWFyD7wDAAIAAL4DAAHAAwAADgAGAaABAAAAAQICCwC+AwABwAMBAQjqCMAA4cAB4ikpvAMBBAEACg4OQwYBvgMAAAADAAATADjhAAAAQuIAAAAE4wAAACQBACm8AwECA10OQwYBwAMAAAADAAEQADjhAAAAQuIAAAC/ACQBACm8AwUCA04HCDIyMjI=) with attached 0.1 NEAR
- Loaded master account test.near key from /home/bo/.near/validator_key.json with public key = ed25519:XXqxAHP1ZRcwCwBTr1MbdF9NM7UVynuTnxhZfFeE5UJ
- Doing account.functionCall()
- Transaction Id Df7txPSFWwaBLTz61pSxoVrPPu6qY7fUTJ31xuQtXDBf
- To see the transaction in the transaction explorer, please open this url in your browser
- http://localhost:9001/transactions/Df7txPSFWwaBLTz61pSxoVrPPu6qY7fUTJ31xuQtXDBf
- ''
-
-
-
+6. If you want to remove the js contract and withdraw the storage deposit, use:
```sh
-near-sdk-js (master) near js call test.near hello --accountId test.near --deposit 0.1 --jsvm test.near
+near js remove --accountId --jsvm
```
-
-Or use the raw CLI call instead
-
-
- near-sdk-js (master) near call test.near call_js_contract --accountId test.near --base64 --args $(node encode_call.js test.near hello '')
+### General steps to run examples on testnet
+1. `export NEAR_ENV=testnet`
+2. `cd examples/`
+3. `yarn && yarn build` to get .base64 file (JS smart-contract).
+4. deploy, call and remove JS contract is same as above, except is `jsvm.testnet`. This is also the default value, so you omit `--jsvm`.
-
-
+## Advanced guides
-
-Example output
-
+### Manual setup with npm package
- Scheduling a call: test.near.call_js_contract(anN2bXRlc3Rlci50ZXN0bmV0AGhlbGxvAA==)
- Loaded master account test.near key from /home/bo/.near/validator_key.json with public key = ed25519:XXqxAHP1ZRcwCwBTr1MbdF9NM7UVynuTnxhZfFeE5UJ
- Doing account.functionCall()
- Receipt: AcRRGeR16FYg5AEMZ163v5Av1NanZtRHocDUvmGTvoYN
- Log [test.near]: Hello Near
- Transaction Id GkitU1Cm5bdQJWe6bzkYganiS9tfetuY4buqGFypvQWL
- To see the transaction in the transaction explorer, please open this url in your browser
- http://localhost:9001/transactions/GkitU1Cm5bdQJWe6bzkYganiS9tfetuY4buqGFypvQWL
- ''
-
-
-
-
-### On Testnet
-Latest master version of near-sdk-js enclave has been deployed on `jsvm.testnet`. You can use it or deploy your own copy of jsvm, which is simiar to the steps for deploy on local node. The following is the step to deploy and call your contract on `jsvm.testnet`.
-
-1. Build the contract
+You can also layout your project by install the npm package manually:
```
-near-sdk-js (master) ./builder.sh examples/low-level/hello_near.js
+npm install near-sdk-js
+# or
+yarn add near-sdk-js
```
-2. Create an account on testnet wallet. Login it with near-cli:
-```sh
-near-sdk-js (master) export NEAR_ENV=testnet
-near-sdk-js (master) near login
-```
+### NEAR-SDK-JS contributor setup
-
-Example output
-
-
- Please authorize NEAR CLI on at least one of your accounts.
-
- If your browser doesn't automatically open, please visit this URL
- https://wallet.testnet.near.org/login/?referrer=NEAR+CLI&public_key=ed25519%3A6eNw1uLsVbvHJhPrcN9Rj9wefqfzxJ2tz7VqxY8m3F88&success_url=http%3A%2F%2F127.0.0.1%3A5000
- Please authorize at least one account at the URL above.
-
- Which account did you authorize for use with NEAR CLI?
- Enter it here (if not redirected automatically):
- Logged in as [ jsvmtester.testnet ] with public key [ ed25519:6eNw1u... ] successfully
-
-
-
+It is tested on Ubuntu 20.04, Intel Mac and M1 Mac. Other linux should also work but they're not tested.
-3. Deploy the JS contract:
-```sh
-near-sdk-js (master) export JSVM_ACCOUNT=jsvm.testnet
-near-sdk-js (master) near js call deploy --accountId jsvmtester.testnet --base64File hello_near.base64 --deposit 0.1 --jsvm $JSVM_ACCOUNT
-```
+1. Make sure you have `wget`, `make`, `cmake` and `nodejs`. On Linux, also make sure you have `gcc`.
+2. Run `make` to get platform specific `qjsc` and `jsvm` contract in `res` folder.
-
-Or use the raw CLI call instead
-
- near-sdk-js (master) near call $JSVM_ACCOUNT deploy_js_contract --accountId jsvmtester.testnet --base64 --args $(cat hello_near.base64) --deposit 0.1
+### Low level way to invoke NEAR-CLI
-
-
+`near js` subcommand in near-cli is a recent feature. Under the hood, it is encoding a special function call to jsvm contract.
+#### Deploy a JS contract
-Example output
+The equivalent raw command is:
- Scheduling a call: jsvm.testnet.deploy_js_contract(AgYsZXhhbXBsZXMvaGVsbG9fbmVhci5qcwpoZWxsbwxoZWxsbzIGZW52BmxvZxRIZWxsbyBOZWFyD7wDAAIAAL4DAAHAAwAADgAGAaABAAAAAQICCwC+AwABwAMBAQjqCMAA4cAB4ikpvAMBBAEACg4OQwYBvgMAAAADAAATADjhAAAAQuIAAAAE4wAAACQBACm8AwECA10OQwYBwAMAAAADAAEQADjhAAAAQuIAAAC/ACQBACm8AwUCA04HCDIyMjI=) with attached 0.1 NEAR
- Doing account.functionCall()
- Transaction Id 46vC327SWs7JNV7G3XMHkRzETyc6WuxwkdwLhV6Go2kp
- To see the transaction in the transaction explorer, please open this url in your browser
- https://explorer.testnet.near.org/transactions/46vC327SWs7JNV7G3XMHkRzETyc6WuxwkdwLhV6Go2kp
- ''
+ near call deploy_js_contract --accountId --args $(cat .base64) --base64 --deposit 0.1
-Note that, in order to deploy the contract, the deployer need to deposit sufficient amount of NEAR to cover storage deposit. It's roughly 0.01 NEAR for 1KB of contract. If you deposit more than required, the additional part will be refunded. If no adequate deposit is attached, the deploy will failed with a panic. If future deployment increase or decrease in size, the difference will need to be paid or refunded, respectively.
+#### Call a JS contract
-4. Call the JS contract:
-```sh
-near-sdk-js (master) near js call jsvmtester.testnet hello --accountId jsvmtester.testnet --deposit 0.1 --jsvm $JSVM_ACCOUNT
-```
-Or use the raw CLI call instead
+The equivalent raw command is:
- near-sdk-js (master) near call $JSVM_ACCOUNT call_js_contract --accountId jsvmtester.testnet --args $(node encode_call.js jsvmtester.near hello '') --base64
-
-
-
-
-
-Example output
-
+ near call call_js_contract --accountId --args --base64
- Scheduling a call: jsvm.testnet.call_js_contract(anN2bXRlc3Rlci50ZXN0bmV0AGhlbGxvAA==)
- Doing account.functionCall()
- Receipt: 4Mn5d3Kc4n67MxQkcEmi4gxKbrrKXvJE9Rin3q3fdCsQ
- Log [jsvm.testnet]: Hello Near
- Transaction Id 43K5sjgVeWCYzuDJ3S6j5XHxQnRY8w1TQ84MiDxdtHp1
- To see the transaction in the transaction explorer, please open this url in your browser
- https://explorer.testnet.near.org/transactions/43K5sjgVeWCYzuDJ3S6j5XHxQnRY8w1TQ84MiDxdtHp1
- ''
+ # where `` can be obtained by:
+ node encode_call.js
-```sh
-near-sdk-js (master) near js call jsvmtester.testnet hello --accountId jsvmtester2.testnet --deposit 0.1 --jsvm $JSVM_ACCOUNT
-```
+#### Remove a JS contract
-Or use the raw CLI call instead
+The equivalent raw command is:
- near-sdk-js (master) near call $JSVM_ACCOUNT call_js_contract --accountId jsvmtester2.testnet --args $(node encode_call.js jsvmtester.near hello '') --base64
-
-
-
-
-
-Example output
-
-
- Scheduling a call: jsvm.testnet.call_js_contract(anN2bXRlc3Rlci50ZXN0bmV0AGhlbGxvAA==)
- Doing account.functionCall()
- Receipt: DzysE3ZNG8fBY4djq1KDYyDLs53jga2Lxpou2kjm3HzC
- Log [jsvm.testnet]: Hello Near
- Transaction Id AGRHcCCBCFex2hiXQh5BhFDoq7bN1eVoULhSyL4zgMRA
- To see the transaction in the transaction explorer, please open this url in your browser
- https://explorer.testnet.near.org/transactions/AGRHcCCBCFex2hiXQh5BhFDoq7bN1eVoULhSyL4zgMRA
- ''
+ near call remove_js_contract --accountId
-Note that, The second call shows this method can be call by anyone (`jsvmtester2.testnet` in above example, make sure you login the account with `near login`), not just the one who deployed this JS contract (`jsvmtester.testnet`).
-
## NEAR-SDK-JS Low Level API Reference
Use `env.func_name(args)` to call low level APIs in JavaScript contracts. `env` is already imported before contract start. For example, `env.read_register(0)`.
From 294f9ed8f9160f98e5241b6bb41c30e91063cc8f Mon Sep 17 00:00:00 2001
From: Bo Yao
Date: Thu, 2 Jun 2022 11:26:04 +0800
Subject: [PATCH 2/7] finish update readme
---
README.md | 252 ++++++++++++++++++++-------------------------------
src/api.js | 12 ++-
src/utils.js | 4 +
3 files changed, 114 insertions(+), 154 deletions(-)
diff --git a/README.md b/README.md
index 9141b212d..e9bfde2ce 100644
--- a/README.md
+++ b/README.md
@@ -14,9 +14,8 @@ There are a couple of contract examples in the project:
- [Lockable fungible token](https://github.com/near/near-sdk-js/tree/master/examples/lockable-fungible-token)
- [Non fungible token](https://github.com/near/near-sdk-js/tree/master/examples/non-fungible-token)
- [Status message board](https://github.com/near/near-sdk-js/tree/master/examples/status-message)
-- [Status message board with search](https://github.com/near/near-sdk-js/tree/master/examples/status-message-collections)
-The general steps to run these contracts are same. You can also try them by following their corresponding READMEs.
+The general steps to run these contracts are same. You can also follow their corresponding READMEs to build, test and run the contracts.
### General steps to run examples locally
1. Use near-cli to deploy `jsvm.wasm` from the `res` folder to one of account you controlled. For example, `jsvm.`:
@@ -47,7 +46,22 @@ near js remove --accountId --jsvm
1. `export NEAR_ENV=testnet`
2. `cd examples/`
3. `yarn && yarn build` to get .base64 file (JS smart-contract).
-4. deploy, call and remove JS contract is same as above, except is `jsvm.testnet`. This is also the default value, so you omit `--jsvm`.
+4. Deploy, call and remove JS contract is same as above, except is `jsvm.testnet`. This is also the default value, so you omit `--jsvm`.
+
+## Error Handling in NEAR-SDK-JS
+
+If you want to indicate an error happened and fail the transaction, just throw an error object in JavaScript. Our JSVM runtime will detect and automatically invoke `panic_utf8` with `"{error.message}\n:{error.stack}"`. As a result, transaction will fail with `"Smart contract panicked: {error.message}\n{error.stack}"` error message. You can also use an error utilities library to organize your errors, such as verror.
+
+When your JS code or library throws an error, uncaught, the transaction will also fail with GuestPanic error, with the error message and stacktrace.
+
+When call host function with inappropriate type, means incorrect number of arguments or arg is not expected type:
+ - if arguments less than params, remaining argument are set as 'undefined'
+ - if arguments more than params, remaining argument are ignored
+ - if argument is different than the required type, it'll be coerced to required type
+ - if argument is different than the required type but cannot be coerced, will throw runtime type error, also with message and stacktrace
+
+## Test
+We recommend to use near-workspaces to write tests for your smart contracts. See any of the examples for how tests are setup and written.
## Advanced guides
@@ -55,9 +69,9 @@ near js remove --accountId --jsvm
You can also layout your project by install the npm package manually:
```
-npm install near-sdk-js
-# or
yarn add near-sdk-js
+# or
+npm install near-sdk-js
```
### NEAR-SDK-JS contributor setup
@@ -68,6 +82,10 @@ It is tested on Ubuntu 20.04, Intel Mac and M1 Mac. Other linux should also work
2. Run `make` to get platform specific `qjsc` and `jsvm` contract in `res` folder.
+### Run NEAR-SDK-JS tests
+See https://github.com/near/near-sdk-js/tree/master/tests
+
+
### Low level way to invoke NEAR-CLI
`near js` subcommand in near-cli is a recent feature. Under the hood, it is encoding a special function call to jsvm contract.
@@ -92,7 +110,7 @@ It is tested on Ubuntu 20.04, Intel Mac and M1 Mac. Other linux should also work
near call call_js_contract --accountId --args --base64
# where `` can be obtained by:
- node encode_call.js
+ node scripts/encode_call.js
@@ -108,10 +126,17 @@ It is tested on Ubuntu 20.04, Intel Mac and M1 Mac. Other linux should also work
-## NEAR-SDK-JS Low Level API Reference
+## NEAR-SDK-JS API Reference
-Use `env.func_name(args)` to call low level APIs in JavaScript contracts. `env` is already imported before contract start. For example, `env.read_register(0)`.
-To use nightly host functions, such as `alt_bn128_g1_sum`, the enclave contract need to be built with `NEAR_NIGHTLY=1 ./build.sh` and deployed to a nearcore node that has nightly enabled.
+All NEAR blockchain provided functionality (host functions) are defined in `src/api.js` and exported as `near`. You can use them by:
+```js
+import {near} from 'near-sdk-js'
+
+// near.. e.g.:
+let signer = near.signerAccountId()
+```
+
+To use nightly host functions, such as `altBn128G1Sum`, the enclave contract need to be built with `NEAR_NIGHTLY=1 ./build.sh` and deployed to a nearcore node that has nightly enabled.
### About Type
@@ -123,213 +148,136 @@ To use nightly host functions, such as `alt_bn128_g1_sum`, the enclave contract
It's intentional to represent string and bytes in this way because QuickJS doesn't have ArrayBuffer in C API.
-- The signature may differs from Rust APIs. This is because JavaScript doesn't have pointers and not possible to pass pointer as arguments. So, Instead of `data_len: u64, data_ptr: u64`, JavaScript API pass the data directly: `data: String`.
-- The lowest level Rust API cannot return value bigger than 64 bit integer. So some of the API pass pointer as Uint64 and the Rust function write return data at the location specified by pointer. In JavaScript we don't have this limitation and value is returned as API function return.
-
-
-### About commented APIs
-Some of the APIs below starts with `//`. This means this API is provided by nearcore, however they are intentionally removed for the JavaScript Enclave. The reason and alternative are documented in each API section.
-
-### Registers API
-
-```
-function read_register(register_id: Uint64): String;
-function register_len(register_id: Uint64): Uint64;
-function write_register(register_id: Uint64, data: String);
-```
-
### Context API
```
-// function current_account_id(register_id: Uint64);
-function signer_account_id(register_id: Uint64);
-function signer_account_pk(register_id: Uint64);
-function predecessor_account_id(register_id: Uint64);
-// function input(register_id: Uint64);
-function block_index(): Uint64;
-function block_timestamp(): Uint64;
-function epoch_height(): Uint64;
-// function storage_usage(): Uint64;
+function signerAccountId(): String;
+function signerAccountPk(): String;
+function predecessorAccountId(): String;
+function blockIndex(): Uint64;
+function blockTimestamp(): Uint64;
+function epochHeight(): Uint64;
```
-The `current_account_id` would always puts the account id of the JavaScript VM contract account in given register. The naming `current_account_id` is therefore confusing and not as helpful as a Rust contract. In some case, developer may want to get JavaScript VM contract account name, for example, determines whether it's running on testnet or mainnet, and behaves differently. So we expose this functionality under `jsvm_account_id()`.
-
-The `input` puts the argument passed to call the contract in given register. In JavaScript VM, this is encoded as `"js_contract_name\0method_name\0args...`. This format isn't very convinient to developer, therefore, separate API `jsvm_js_contract_name`, `jsvm_method_name` and `jsvm_args` are provided.
-
-The `storage_usage` return the storage bytes used by JavaScript VM contract. User doesn't care about the storage usage of the JSVM. Instead, users care about storage usage of a given JavaScript contract. This can be obtained by `storage_read` and count the sum of `register_len`.
### Economics API
```
-// function account_balance(): Uint128;
-// function account_locked_balance(): Uint128;
-function attached_deposit(): Uint128;
-function prepaid_gas(): Uint64;
-function used_gas(): Uint64;
+function attachedDeposit(): Uint128;
+function prepaidGas(): Uint64;
+function usedGas(): Uint64;
```
-The `account_balance` and `account_locked_balance` returns balance and locked_balance of JavaScript VM. Those are also not cared by users.
-
### Math API
-
```
-function random_seed(register_id: Uint64);
-function sha256(value: String, register_id: Uint64);
-function keccak256(value: String, register_id: Uint64);
-function keccak512(value: String, register_id: Uint64);
-function ripemd160(value: String, register_id: Uint64);
-function ecrecover(hash: String, sign: String, v: Uint64, malleability_flag: Uint64, register_id: Uint64): Uint64;
+function randomSeed(): String;
+function sha256(value: String): String;
+function keccak256(value: String): String;
+function keccak512(value: String): String;
+function ripemd160(value: String): String;
+function ecrecover(hash: String, sign: String, v: Uint64, malleability_flag: Uint64): String | null;
```
### Miscellaneous API
-
```
-// function value_return(value: String);
function panic(msg?: String);
-function panic_utf8(msg: String);
+function panicUtf8(msg: String);
function log(msg: String);
-function log_utf8(msg: String);
-function log_utf16(msg: String);
-// Name confliction with WASI. Can be re-exported with a different name on NEAR side with a protocol upgrade
-// Or, this is actually not a primitive, can be implement with log and panic host functions in C side or JS side.
-// function abort(msg_ptr: Uint32, filename_ptr: Uint32, u32: Uint32, col: Uint32);
-```
-
-The `value_return` is a NEAR primitive that puts the value to return in a receipt. However we would want to access it as a JavaScript return value in a cross contract call. So we have a new API `jsvm_value_return`, which does return the value in receipt and also as a JavaScript value returned by `jsvm_call`. The `jsvm_value_return` should be used whenever you need `value_return`.
-
-### Promises API
-
-```
-function promise_create(account_id: String, method_name: String, arguments: String, amount: Uint128, gas: Uint64): Uint64;
-function promise_then(promise_index: Uint64, account_id: String, method_name: String, arguments: String, amount: Uint128, gas: Uint64): Uint64;
-function promise_and(...promise_idx: Uint64): Uint64;
-function promise_batch_create(account_id: String): Uint64;
-function promise_batch_then(promise_index: Uint64, account_id: String): Uint64;
-```
-
-### Promise API actions
-
-```
-// function promise_batch_action_create_account(promise_index: Uint64); // not allow users to create *.jsvm account
-// function promise_batch_action_deploy_contract(promise_index: Uint64, code: String); // batch actions are applied to create_account_action, but that is not allowed
-// function promise_batch_action_function_call(promise_index: Uint64, method_name: String, arguments: String, amount: Uint128, gas: Uint64);
-// function promise_batch_action_transfer(promise_index: Uint64, amount: Uint128);
-// function promise_batch_action_stake(promise_index: Uint64, amount: Uint128, public_key: String);
-// function promise_batch_action_add_key_with_full_access(promise_index: Uint64, public_key: String, nonce: Uint64);
-// function promise_batch_action_add_key_with_function_call(promise_index: Uint64, public_key: String, nonce: Uint64, allowance: Uint128, receiver_id: String, method_names: String);
-// function promise_batch_action_delete_key(promise_index: Uint64, public_key: String);
-// function promise_batch_action_delete_account(promise_index: Uint64, beneficiary_id: String);
-```
-
-All Promise batch actions act on the JSVM contract, creating a subaccount of it and acting on it. JSVM would be a common VM used by the community instead of a Rust contract owned by the deployer. Terefore, creating subaccounts and subsequent actions towards subaccounts are not allowed.
-
-### Promise API results
-
-```
-function promise_results_count(void): Uint64;
-function promise_result(result_idx: Uint64, register_id: Uint64): Uint64;
-function promise_return(promise_idx: Uint64);
+function logUtf8(msg: String);
+function logUtf16(msg: String);
```
### Storage API
```
-// function storage_write(key: String, value: String, register_id: Uint64): Uint64; // user can only access contract's storage
-function storage_read(key: String, register_id: Uint64): Uint64;
-// function storage_remove(key: String, register_id: Uint64): Uint64; // same as storage_write
-function storage_has_key(key: String): Uint64;
+function storageRead(key: String): String | null;
+function storageHasKey(key: String): bool;
```
-The `storage_write` and `storage_remove` have access to all JavaScript contract codes and states deployed on JSVM. User can only write to their account owned code and state, as a substate of the JSVM. Therefor these two APIs are disallowed. Use `jsvm_storage_write` and `jsvm_storage_remove` instead. Read to other people owned code and state is allowed, as they're public as part of the blockchain anyway.
### Validator API
```
-function validator_stake(account_id: String): Uint128;
-function validator_total_stake(): Uint128;
+function validatorStake(account_id: String): Uint128;
+function validatorTotalStake(): Uint128;
```
### Alt BN128
```
-function alt_bn128_g1_multiexp(value: String, register_id: Uint64);
-function alt_bn128_g1_sum(value: String, register_id: Uint64);
-function alt_bn128_pairing_check(value: String): Uint64;
+function altBn128G1Multiexp(value: String): String;
+function altBn128G1Sum(value: String): String;
+function altBn128PairingCheck(value: String): bool;
```
-## JSVM Specific APIs
+### JSVM Specific APIs
Due to the design of JavaScript VM Contract, some additonal APIs are provided to obtain context, access storage and cross contract call. Since they're not documented at [NEAR nomicon](https://nomicon.io/). They're explained here.
-### Obtain Context
+#### Obtain Context
```
-function jsvm_account_id(register_id: Uint64);
-function jsvm_js_contract_name(register_id: Uint64);
-function jsvm_method_name(register_id: Uint64);
-function jsvm_args(register_id: Uint64);
+function jsvmAccountId(): String;
+function jsvmJsContractName(): String;
+function jsvmMethodName(): String;
+function jsvmArgs(): String;
```
-The `jsvm_account_id` put the JavaScript VM's contract account ID into given register.
+The `jsvmAccountId` returns the JavaScript VM's contract account ID.
-The `jsvm_js_contract_name`, when called, put the JavaScript contract name that are called at the moment, into given register.
+The `jsvmJsContractName`, when called, returns the JavaScript contract name that are called at the moment.
-The `jsvm_method_name` put the method name being called into given register.
+The `jsvmJsContractName` returns the method name being called.
-The `jsvm_args` return the arguments passed to the method, into given register.
+The `jsvmArgs` return the arguments passed to the method.
-### Storage Access
+#### Storage Access
```
-function jsvm_storage_write(key: String, value: String, register_id: Uint64): Uint64;
-function jsvm_storage_read(key: String, register_id: Uint64): Uint64;
-function jsvm_storage_remove(key: String, register_id: Uint64): Uint64;
-function jsvm_storage_has_key(key: String): Uint64;
+function jsvmStorageWrite(key: String, value: String): bool;
+function jsvmStorageRead(key: String): String | null;
+function jsvmStorageRemove(key: String): bool;
+function jsvmStorageHasKey(key: String): bool;
+function storageGetEvicted(): String;
```
-These are equivalent to `storage_*` but access limit to the substate of current JS contract. The `jsvm_storage_write` and `jsvm_storage_remove` require and refund deposit to cover the storage delta. `jsvm_storage_*` access the substate of current JS contract by prefix the key of current JS contract name (deployer's account id). You can use `storage_read` and `storage_has_key` to get code and state of other JS contracts. More specifically: code of `contractA` is stored under the key `contractA/code`. state of `contractA` is stored under `contractA/state/` concat with developer specifid key. And:
+These are equivalent to `storage*` but access limit to the substate of current JS contract. The `jsvmStorageWrite` and `jsvmStorageRemove` require and refund deposit to cover the storage delta. `jsvmStorage*` access the substate of current JS contract by prefix the key of current JS contract name (deployer's account id). You can use `storageRead` and `storageHasKey` to get code and state of other JS contracts. More specifically: code of `contractA` is stored under the key `contractA/code`. state of `contractA` is stored under `contractA/state/` concat with developer specifid key. And:
```
-jsvm_storage_read(k, register_id)
+jsvmStorageRead(k)
// equvalent to
-storage_read(jsvm_js_contract_name + '/state/' + k)
+storageRead(jsvmJsContractName() + '/state/' + k)
```
-### Cross Contract Call
+When `jsvmStorageWrite` write to a key that already exists, the old value would be saved and can be obtained by `storageGetEvicted()`. In this case, jsvmStorageWrite returns `true`. If key doesn't exist before, returns `false`.
+
+When `jsvmStroageRemove` remove a key that exists, the old value would be saved and can be obtained by `storageGetEvicted()`. In this case, jsvmStroageRemove returns `true`. If key doesn't exist before, nothing is removed and returns `false`.
+
+#### Cross Contract Call
```
-function jsvm_value_return(value: String);
-function jsvm_call(contract_name: String, method: String, args: String, register_id: Uint64);
+function jsvmValueReturn(value: String);
+function jsvmCall(contract_name: String, method: String, args: String): any;
+function jsvmCallRaw(contract_name: String, method: String, args: String): String;
```
-The `jsvm_value_return` is the version of `value_return` that should be used in all JavaScript contracts. It play well with `jsvm_call`.
+The `jsvmValueReturn` is the version of `valueReturn` that should be used in all JavaScript contracts. It play well with `jsvmCall`.
-The `jsvm_call` invoke a synchronous cross contract call, to the given JavaScript `contract_name`, `method` with `args`. And capture the value returned from the call and stored in `register_id`.
+The `jsvmCall` invoke a synchronous cross contract call, to the given JavaScript `contract_name`, `method` with `args`. And returned the return value parsed as JSON into a JS object.
-## Error Handling in NEAR-SDK-JS
+The `jsvmCallRaw` is similar to `jsvmCall`, but return the raw, unparsed String.
-### Error handling behavior
+### APIs not available in JSVM
+Due to the architecture of the JSVM, some NEAR host functions, part of Standalone SDK or Rust SDK, are not revelant or being replaced by above JSVM specific APIs. Those unavailable APIs are explained here.
-- when js throws an error, uncatched, then transaction fails with GuestPanic error, with the user js error message and stacktrace
-- when call host function with inappropriate type, means incorrect number of arguments or arg is not expected type:
- - if arguments less than params, remaining argument are set as 'undefined'
- - if arguments more than params, remaining argument are ignored
- - if argument is different than the required type, it'll be coerced to required type
- - if argument is different than the required type but cannot be coerced, will throw runtime type error, also with message and stacktrace
+- The `current_account_id` would always puts the account id of the JavaScript VM contract account in given register. The naming `current_account_id` is therefore confusing and not as helpful as a Rust contract. In some case, developer may want to get JavaScript VM contract account name, for example, determines whether it's running on testnet or mainnet, and behaves differently. So we expose this functionality under `jsvm_account_id()`.
+
+- The `input` puts the argument passed to call the contract in given register. In JavaScript VM, this is encoded as `"js_contract_name\0method_name\0args...`. This format isn't very convinient to developer, therefore, separate API `jsvm_js_contract_name`, `jsvm_method_name` and `jsvm_args` are provided.
-### The error reporting capability of a wasm contract
-Smart contract can only use `panic` or `panic_utf8` to abort from execution. That is of error kind `GuestPanic {msg}`. It displays in RPC as `"Smart contract panicked: {msg}"`
-And only `panic_utf8` can set that message.
-Other than this, if calls a host function, it can returns error provided by that host function. For example, any host function can return a `GasExceeded`. `log_utf8` can return `BadUTF8`. This behavior is part of protocol and we cannot control or trigger in JavaScript (without calling `env.*`).
+- The `storage_usage` return the storage bytes used by JavaScript VM contract. User doesn't care about the storage usage of the JSVM. Instead, users care about storage usage of a given JavaScript contract. This can be obtained by `storage_read` and count the sum of `register_len`.
-### Use errors
-You can throw an error in JavaScript. Our quickjs runtime will detect and automatically invoke `panic_utf8` with `"{error.message}\n:{error.stack}"`. As a result, transaction will fail with `"Smart contract panicked: {error.message}\n{error.stack}"` error message.
+- The `account_balance` and `account_locked_balance` returns balance and locked_balance of JavaScript VM. Those are also not cared by users.
-### Use verror
-User can use verror this way:
-1. catch an error, attach information to it
-2. return/rethrow the error, attach more information to it
-3. throw the final verror, `throw e`, same as in nodejs.
+- The `value_return` is a NEAR primitive that puts the value to return in a receipt. However we would want to access it as a JavaScript return value in a cross contract call. So we have a new API `jsvm_value_return`, which does return the value in receipt and also as a JavaScript value returned by `jsvm_call`. The `jsvm_value_return` should be used whenever you need `value_return`.
-Under the hood, our quickjs runtime would take the final throwed error, and invoke panic_utf8("{error.message}\n{error.stack}")
+- `abort` is intended to mark error location (line number). A full stacktrace with line numbers is provided by QuickJS, available when you throw a JS Error. So this API isn't needed.
-## Debug and Test
-To get more debug utilities, such as debug print (`debug.log`) and logging stacktrace, you can build JSVM with sandbox flag: `NEAR_SANDBOX=1 ./build.sh`. A `jsvm_sandbox.wasm` will be build in current directory. You can then deploy sandbox versioned jsvm to a local [near-sandbox](https://github.com/near/sandbox). near-sandbox can be launched either manually or via the official testing framework [near-workspaces](https://github.com/near/workspaces-js). We recommend to use near-workspaces to write tests for your smart contracts. An example of use near-workspaces in a JS contract project can be found in `examples/project/`.
+- Promise APIs act on the JSVM contract and could create subaccount, use the balance from JSVM account.JSVM would be a common VM used by the community instead of a Rust contract owned by the deployer. Therefore, promise APIs are not allowed.
-Note that, `jsvm.wasm` can be used for sandbox/near-workspaces as well. But to debug print, you need to use `jsvm_sandbox.wasm` instead.
+- The `storage_write` and `storage_remove` have access to all JavaScript contract codes and states deployed on JSVM. User can only write to their account owned code and state, as a substate of the JSVM. Therefor these two APIs are disallowed. Use `jsvm_storage_write` and `jsvm_storage_remove` instead. Read to other people owned code and state is allowed, as they're public as part of the blockchain anyway.
diff --git a/src/api.js b/src/api.js
index aa2c34956..99052817e 100644
--- a/src/api.js
+++ b/src/api.js
@@ -122,9 +122,17 @@ export function jsvmStorageHasKey(key) {
return false
}
-export function jsvmCall(contractName, method, args) {
+export function jsvmCallRaw(contractName, method, args) {
env.jsvm_call(contractName, method, JSON.stringify(args), 0)
- return JSON.parse(env.read_register(0) || 'null')
+ return env.read_register(0)
+}
+
+export function jsvmCall(contractName, method, args) {
+ let ret = jsvmCallRaw(contractName, method, args)
+ if (ret === null) {
+ return ret
+ }
+ return JSON.parse(ret)
}
export function storageGetEvicted() {
diff --git a/src/utils.js b/src/utils.js
index f78570d02..79a336afb 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -12,4 +12,8 @@ export function stringToU8Array(string) {
ret[i] = string.charCodeAt(i)
}
return ret
+}
+
+export function encodeCall(contract, method, args) {
+ return Buffer.concat([Buffer.from(contract), Buffer.from([0]), Buffer.from(method), Buffer.from([0]), Buffer.from(JSON.stringify(args))])
}
\ No newline at end of file
From a005793564df356b845e63e7b9c3e235e8ad202f Mon Sep 17 00:00:00 2001
From: Bo Yao
Date: Thu, 2 Jun 2022 13:09:47 +0800
Subject: [PATCH 3/7] remove promise apis from jsvm
---
jsvm/jsvm.c | 139 --------------------------------------------------
res/jsvm.wasm | Bin 500454 -> 498128 bytes
2 files changed, 139 deletions(-)
diff --git a/jsvm/jsvm.c b/jsvm/jsvm.c
index c44926b87..4befcd311 100644
--- a/jsvm/jsvm.c
+++ b/jsvm/jsvm.c
@@ -65,17 +65,10 @@ extern void panic(void);
extern void panic_utf8(uint64_t len, uint64_t ptr);
extern void log_utf8(uint64_t len, uint64_t ptr);
extern void log_utf16(uint64_t len, uint64_t ptr);
-// Name confliction with WASI. Can be re-exported with a different name on NEAR side with a protocol upgrade
-// Or, this is actually not a primitive, can be implement with log and panic host functions in C side or JS side.
-// extern void abort(uint32_t msg_ptr, uint32_t filename_ptr, uint32_t u32, uint32_t col);
// ################
// # Promises API #
// ################
-extern uint64_t promise_create(uint64_t account_id_len, uint64_t account_id_ptr, uint64_t method_name_len, uint64_t method_name_ptr, uint64_t arguments_len, uint64_t arguments_ptr, uint64_t amount_ptr, uint64_t gas);
-extern uint64_t promise_then(uint64_t promise_index, uint64_t account_id_len, uint64_t account_id_ptr, uint64_t method_name_len, uint64_t method_name_ptr, uint64_t arguments_len, uint64_t arguments_ptr, uint64_t amount_ptr, uint64_t gas);
-extern uint64_t promise_and(uint64_t promise_idx_ptr, uint64_t promise_idx_count);
extern uint64_t promise_batch_create(uint64_t account_id_len, uint64_t account_id_ptr);
-extern uint64_t promise_batch_then(uint64_t promise_index, uint64_t account_id_len, uint64_t account_id_ptr);
// #######################
// # Promise API actions #
// #######################
@@ -83,8 +76,6 @@ extern void promise_batch_action_transfer(uint64_t promise_index, uint64_t amoun
// #######################
// # Promise API results #
// #######################
-extern uint64_t promise_results_count(void);
-extern uint64_t promise_result(uint64_t result_idx, uint64_t register_id);
extern void promise_return(uint64_t promise_idx);
// ###############
// # Storage API #
@@ -460,128 +451,6 @@ static JSValue near_log_utf16(JSContext *ctx, JSValueConst this_val, int argc, J
return JS_UNDEFINED;
}
-static JSValue near_promise_create(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- const char *account_id_ptr, *method_name_ptr, *arguments_ptr;
- size_t account_id_len, method_name_len, arguments_len;
- uint64_t amount_ptr[2]; // amount is u128
- uint64_t gas, ret;
-
- account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[0]);
- method_name_ptr = JS_ToCStringLen(ctx, &method_name_len, argv[1]);
- arguments_ptr = JS_ToCStringLenRaw(ctx, &arguments_len, argv[2]);
- if (quickjs_to_u128(ctx, argv[3], amount_ptr) != 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint128 for amount");
- }
- if (JS_ToUint64Ext(ctx, &gas, argv[4]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for gas");
- }
-
- ret = promise_create(account_id_len, (uint64_t)account_id_ptr, method_name_len, (uint64_t)method_name_ptr, arguments_len, (uint64_t)arguments_ptr, (uint64_t)amount_ptr, gas);
-
- return JS_NewBigUint64(ctx, ret);
-}
-
-static JSValue near_promise_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- uint64_t promise_index;
- const char *account_id_ptr, *method_name_ptr, *arguments_ptr;
- size_t account_id_len, method_name_len, arguments_len;
- uint64_t amount_ptr[2]; // amount is u128
- uint64_t gas, ret;
-
- if (JS_ToUint64Ext(ctx, &promise_index, argv[0]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_index");
- }
- account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[1]);
- method_name_ptr = JS_ToCStringLen(ctx, &method_name_len, argv[2]);
- arguments_ptr = JS_ToCStringLenRaw(ctx, &arguments_len, argv[3]);
- if (quickjs_to_u128(ctx, argv[4], amount_ptr) != 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint128 for amount");
- }
- if (JS_ToUint64Ext(ctx, &gas, argv[5]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for gas");
- }
-
- ret = promise_then(promise_index, account_id_len, (uint64_t)account_id_ptr, method_name_len, (uint64_t)method_name_ptr, arguments_len, (uint64_t)arguments_ptr, (uint64_t)amount_ptr, gas);
-
- return JS_NewBigUint64(ctx, ret);
-}
-
-static JSValue near_promise_and(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- uint64_t promise_idx_ptr[argc], ret;
-
- for(int i = 0; i < argc; i++) {
- if (JS_ToUint64Ext(ctx, &promise_idx_ptr[i], argv[i]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_id");
- }
- }
- ret = promise_and((uint64_t)promise_idx_ptr, argc);
- return JS_NewBigUint64(ctx, ret);
-}
-
-static JSValue near_promise_batch_create(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- const char *account_id_ptr;
- size_t account_id_len;
- uint64_t ret;
-
- account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[0]);
- ret = promise_batch_create(account_id_len, (uint64_t)account_id_ptr);
- return JS_NewBigUint64(ctx, ret);
-}
-
-static JSValue near_promise_batch_then(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- uint64_t promise_index;
- const char *account_id_ptr;
- size_t account_id_len;
- uint64_t ret;
-
- if (JS_ToUint64Ext(ctx, &promise_index, argv[0]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_index");
- }
- account_id_ptr = JS_ToCStringLen(ctx, &account_id_len, argv[1]);
- ret = promise_batch_then(promise_index, account_id_len, (uint64_t)account_id_ptr);
- return JS_NewBigUint64(ctx, ret);
-}
-
-static JSValue near_promise_results_count(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- uint64_t value;
-
- value = promise_results_count();
- return JS_NewBigUint64(ctx, value);
-}
-
-static JSValue near_promise_result(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- uint64_t result_idx, register_id;
- uint64_t ret;
-
- if (JS_ToUint64Ext(ctx, &result_idx, argv[0]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for result_idx");
- }
- if (JS_ToUint64Ext(ctx, ®ister_id, argv[1]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for register_id");
- }
- ret = promise_result(result_idx, register_id);
-
- return JS_NewBigUint64(ctx, ret);
-}
-
-static JSValue near_promise_return(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
-{
- uint64_t promise_idx;
- if (JS_ToUint64Ext(ctx, &promise_idx, argv[0]) < 0) {
- return JS_ThrowTypeError(ctx, "Expect Uint64 for promise_idx");
- }
- promise_return(promise_idx);
-
- return JS_UNDEFINED;
-}
-
const uint64_t STORAGE_PRICE_PER_BYTE_U64 = 10000000000000000000ul;
const char *STORAGE_PRICE_PER_BYTE = "10000000000000000000";
@@ -1151,14 +1020,6 @@ static void js_add_near_host_functions(JSContext* ctx) {
JS_SetPropertyStr(ctx, env, "log", JS_NewCFunction(ctx, near_log, "log", 1));
JS_SetPropertyStr(ctx, env, "log_utf8", JS_NewCFunction(ctx, near_log_utf8, "log_utf8", 1));
JS_SetPropertyStr(ctx, env, "log_utf16", JS_NewCFunction(ctx, near_log_utf16, "log_utf16", 1));
- JS_SetPropertyStr(ctx, env, "promise_create", JS_NewCFunction(ctx, near_promise_create, "promise_create", 5));
- JS_SetPropertyStr(ctx, env, "promise_then", JS_NewCFunction(ctx, near_promise_then, "promise_then", 6));
- JS_SetPropertyStr(ctx, env, "promise_and", JS_NewCFunction(ctx, near_promise_and, "promise_and", 1));
- JS_SetPropertyStr(ctx, env, "promise_batch_create", JS_NewCFunction(ctx, near_promise_batch_create, "promise_batch_create", 1));
- JS_SetPropertyStr(ctx, env, "promise_batch_then", JS_NewCFunction(ctx, near_promise_batch_then, "promise_batch_then", 2));
- JS_SetPropertyStr(ctx, env, "promise_results_count", JS_NewCFunction(ctx, near_promise_results_count, "promise_results_count", 0));
- JS_SetPropertyStr(ctx, env, "promise_result", JS_NewCFunction(ctx, near_promise_result, "promise_result", 2));
- JS_SetPropertyStr(ctx, env, "promise_return", JS_NewCFunction(ctx, near_promise_return, "promise_return", 1));
JS_SetPropertyStr(ctx, env, "storage_read", JS_NewCFunction(ctx, near_storage_read, "storage_read", 2));
JS_SetPropertyStr(ctx, env, "storage_has_key", JS_NewCFunction(ctx, near_storage_has_key, "storage_has_key", 1));
JS_SetPropertyStr(ctx, env, "validator_stake", JS_NewCFunction(ctx, near_validator_stake, "validator_stake", 2));
diff --git a/res/jsvm.wasm b/res/jsvm.wasm
index 1326e3d0dee8b34eb51e065bfed74c4f47a7e0ee..a480b98da6ac7b032aa8dda754c3c93881f519f3 100755
GIT binary patch
delta 117784
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