Pharpend/develop (#1)

* move stuff in here

* reorganizing because zx needs to feel special

* add base58/base64 explainer draft
This commit is contained in:
pharpend
2022-10-05 23:30:49 +09:00
committed by GitHub
parent 5a6a6fb6c3
commit cbb117b504
86 changed files with 8188 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
*.swp
*.swo
jex_mindist
dist
src/jex_include
erl_crash.dump
+16
View File
@@ -0,0 +1,16 @@
ISC License
Copyright (c) 2022 Peter Harpending
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+14
View File
@@ -0,0 +1,14 @@
all: pull build
deploy: pull build mindist push
pull:
jx pull -f
build:
jx build -f
mindist:
jx mindist -f
push:
jx push -f
View File
+5
View File
@@ -0,0 +1,5 @@
{type, library}.
{realm, local}.
{name, parasite}.
{version, "0.1.0"}.
{deps, []}.
+96
View File
@@ -0,0 +1,96 @@
/*******************************************************************
** Compiler API
**
** The manner in which this module is laid out differs meaningfully
** from the `ae_node` module.
**
** - ae_node basically exposes a subset of the node interface as
** functions. It only black-boxes away the networking aspects.
**
** - part of the reason for this is that the data structures that get
** sent to the node tend to be pretty involved (lots of fields)
**
** - in general, the node interface is significantly more complicated
** than the compiler interface
**
** - by contrast, the data structures that get sent to the compiler
** tend to be pretty simple and only have a small number of fields
**
** - the manner in which this manifests is that ae_node functions
** tend to have a weird esoteric data structure as the input,
** because otherwise there would be too many parameters.
**
** here, there are few parameters, and they are passed directly
**
** - in general, the compiler has fewer things it can do, and the
** things it does tend to depend on less information. so this
** interface is significantly simpler than the node interface
*******************************************************************/
import * as net from './net.js';
const URL_COMPILER = 'https://compiler.aepps.com';
// endpoints
const EPT_CompileContract = URL_COMPILER + '/compile';
const EPT_EncodeCalldata = URL_COMPILER + '/encode-calldata';
//-------------------------------------------------------------------
// HELPERS
//-------------------------------------------------------------------
// make a CompileOpts data structure
function
compile_options(filename: string)
: object
{
return {"backend" : "fate",
"file_system" : {},
"src_file" : filename};
}
//-------------------------------------------------------------------
// API CALLS
//-------------------------------------------------------------------
// send back compile response
async function
CompileContract(code : string,
filename : string)
: Promise<Response>
{
let send_obj =
{"code" : code,
"options" : compile_options(filename)};
let response = await net.post_json_response(EPT_CompileContract, send_obj);
return response;
}
async function
EncodeCalldata(code : string,
filename : string,
function_name : string,
function_args : Array<string>)
: Promise<Response>
{
let send_obj =
{"source" : code,
"options" : compile_options(filename),
"function" : function_name,
"arguments" : function_args};
let response = await net.post_json_response(EPT_EncodeCalldata, send_obj);
return response;
}
export {
CompileContract,
EncodeCalldata
}
+272
View File
@@ -0,0 +1,272 @@
/********************************************************************
** Node API: functions for talking to an Aeternity node
**
** In the future, everything that this module does will be replaced
** by the backend.
**
** Functions should be sorted in alphabetical order.
**
** Names are what they are in the documentation
**
** Useful links:
**
** - HTML API docs : https://api-docs.aeternity.io/
** - YAML API docs : https://github.com/aeternity/aeternity/blob/master/apps/aehttp/priv/swagger.yaml
**
********************************************************************/
import * as net from './net.js'
import * as ae_compiler from './ae_compiler.js'
//-------------------------------------------------------------------
// CONSTANTS
//-------------------------------------------------------------------
export const MIN_FEE = 16660000000000;
export const MIN_CONTRACT_FEE = 79080000000000;
export const MIN_GAS_PRICE = 1000000000;
export const URL_MAINNET = "https://mainnet.aeternity.io/v2";
export const URL_TESTNET = "https://testnet.aeternity.io/v2";
//-------------------------------------------------------------------
// CANONICAL TYPES ("MODELS") FROM THE DOCUMENTATION
//
// All of these names are as given in the documentation except `Error`
// (which is a reserve term in JS), renamed to `ErrorReason`
//-------------------------------------------------------------------
// Error
//
// Docs: https://api-docs.aeternity.io/#/definitions/Error
// Docs: https://github.com/aeternity/aeternity/blob/v6.4.0/apps/aehttp/priv/swagger.yaml#L3168-L3172
type ErrorReason = {reason: string};
type Tx = {tx: string};
//-------------------------------------------------------------------
// FUNCTIONS
//
// The names here follow their names in the documentation
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// GetAccountNextNonce: /accounts/{pubkey}/next-nonce
//
// Docs: https://api-docs.aeternity.io/#/account/GetAccountNextNonce
//
// > Get an account's next nonce; This is computed according to
// > whatever is the current account nonce and what transactions are
// > currently present in the transaction pool
//-------------------------------------------------------------------
type GetAccountNextNonce_params = {pubkey : string,
strategy? : "max" | "continuity"};
type GetAccountNextNonce_ret = {next_nonce: string};
async function
GetAccountNextNonce(endpoint_url : string,
params : GetAccountNextNonce_params)
: Promise< GetAccountNextNonce_ret
| ErrorReason>
{
let pubkey = params.pubkey;
let url = `${endpoint_url}/accounts/${pubkey}/next-nonce`;
// if the "strategy" field is present, add it as a ?strategy=x
// option
//
// note if the field is absent from `params`, then
// `params.strategy` will be `undefined`, which in js whacko
// world is "falsy"
let strategy = params.strategy;
if (strategy)
{
let addon = `?strategy=${strategy}`;
url += addon;
}
// irrespective of the response code, this is what we return
// so branching is gay
let ret = await net.get_json(url);
return ret;
}
//-------------------------------------------------------------------
// PostContractCreate
//
// Docs: https://api-docs.aeternity.io/#/contract/PostContractCreate
//-------------------------------------------------------------------
// > Get a contract_create transaction object
type ContractCreateTx = {owner_id : string,
nonce? : number,
code : string,
vm_version : number,
abi_version : number,
deposit : number,
amount : number,
gas : number,
gas_price : number,
fee : number,
ttl? : number,
call_data : string};
async function
PostContractCreate(endpoint_url : string,
body_obj : ContractCreateTx)
: Promise<Response>
{
// console.log('body_obj', body_obj);
let url = `${endpoint_url}/debug/contracts/create`;
let ret = await net.post_json_response(url, body_obj);
return ret;
}
async function
create_contract(whoami : string,
code : string,
filename : string,
init_args : Array<string>)
: Promise<Response>
{
let code_resp = await ae_compiler.CompileContract(code, filename);
let code_json = await code_resp.json();
let bytecode = code_json.bytecode;
let calldata_resp = await ae_compiler.EncodeCalldata(code, filename, "init", init_args);
// assert(calldata_resp.ok);
let calldata_json = await calldata_resp.json();
let calldata = calldata_json.calldata;
let cctx: ContractCreateTx =
{owner_id : whoami,
code : bytecode,
vm_version : 7,
abi_version : 3,
deposit : 0,
amount : 0,
gas : 25000,
gas_price : 1*MIN_GAS_PRICE,
fee : 1*MIN_CONTRACT_FEE,
call_data : calldata};
let ret = await PostContractCreate(URL_TESTNET, cctx);
return ret;
}
//-------------------------------------------------------------------
// PostSpend: /debug/transactions/spend
//
// Docs:
// - Input type : https://api-docs.aeternity.io/#/definitions/SpendTx
// - Return type : https://api-docs.aeternity.io/#/definitions/Tx
// - Function : https://api-docs.aeternity.io/#/transaction/PostSpend
//
// > Get a spend transaction object
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// SpendTx
//
// Docs: https://api-docs.aeternity.io/#/definitions/SpendTx
// Docs: https://github.com/aeternity/aeternity/blob/v6.4.0/apps/aehttp/priv/swagger.yaml#L2187-L2209
//-------------------------------------------------------------------
type SpendTx =
{recipient_id : string,
amount : number,
fee : number,
ttl? : number,
sender_id : string,
nonce? : number,
payload : string};
async function
PostSpend(endpoint_url : string,
body_obj : SpendTx)
: Promise<Tx | ErrorReason>
{
let url = `${endpoint_url}/debug/transactions/spend`;
let ret = await net.post_json(url, body_obj);
return ret;
}
//-------------------------------------------------------------------
// PostTransaction
//
// Docs: https://api-docs.aeternity.io/#/contract/PostTransaction
//
// > Post a new transaction
//-------------------------------------------------------------------
async function
PostTransaction(endpoint_url : string,
body_obj : Tx)
: Promise<Response>
{
// console.log('body_obj', body_obj);
let url = `${endpoint_url}/transactions`;
let ret = await net.post_json_response(url, body_obj);
return ret;
}
//-------------------------------------------------------------------
// GetTransactionInfoByHash
//
// Docs: https://api-docs.aeternity.io/#/contract/GetTransactionInfoByHash
//-------------------------------------------------------------------
async function
GetTransactionInfoByHash(endpoint_url : string,
hash : string)
: Promise<Response>
{
// console.log('body_obj', body_obj);
let url = `${endpoint_url}/transactions/${hash}/info`;
let ret = await net.get_json_response(url);
return ret;
}
//-------------------------------------------------------------------
// EXPORTS
//-------------------------------------------------------------------
// type exports
export type {
ErrorReason,
Tx,
SpendTx,
ContractCreateTx
};
export {
GetAccountNextNonce,
PostContractCreate,
create_contract,
PostSpend,
PostTransaction
};
+85
View File
@@ -0,0 +1,85 @@
//-------------------------------------------------------------------
// Common networking functions
//
// Mozilla fetch docs : https://developer.mozilla.org/en-US/docs/Web/API/fetch
//-------------------------------------------------------------------
/* pf = pretty format
*/
function pf(x : any) : string
{
return JSON.stringify(x, undefined, 4);
}
//-------------------------------------------------------------------
// FUNCTIONS
//-------------------------------------------------------------------
// GET request with return type of JSON
async function
get_json(url: string)
: Promise<any>
{
let response = await fetch(url);
let ret = await response.json();
return ret;
}
// GET request with return type of JSON
async function
get_json_response(url: string)
: Promise<Response>
{
let response = await fetch(url);
//let ret = await response.json();
return response;
}
// POST request with content type of json and return type of JSON
async function
post_json(url : string,
body_obj : any)
: Promise<any>
{
let body_str = pf(body_obj);
let req_opts = {method : 'POST',
body : body_str,
headers : {"Content-Type": "application/json"}};
let response = await fetch(url, req_opts);
let ret = await response.json();
return ret;
}
async function
post_json_response(url : string,
body_obj : any)
: Promise<Response>
{
let body_str = pf(body_obj);
let req_opts = {method : 'POST',
body : body_str,
headers : {"Content-Type": "application/json"}};
let response = await fetch(url, req_opts);
return response;
}
//-------------------------------------------------------------------
// EXPORTS
//-------------------------------------------------------------------
export {
get_json,
get_json_response,
post_json,
post_json_response
}
+16
View File
@@ -0,0 +1,16 @@
{"compilerOptions" : {"target" : "es2022",
"strict" : true,
"esModuleInterop" : true,
"skipLibCheck" : true,
"forceConsistentCasingInFileNames" : true,
"noImplicitAny" : true,
"strictNullChecks" : true,
"strictPropertyInitialization" : true,
"sourceMap" : true,
"outDir" : "dist",
"declaration" : true},
"$schema" : "https://json.schemastore.org/tsconfig",
"display" : "Recommended",
"include" : ["src/**/*"],
"exclude" : ["src/jx_include"],
"composite" : true}