Giter VIP home page Giter VIP logo

tools's Introduction

tools

CI

Zeitgeist JavaScript libraries and tools.

The commandline interface that is built on top of @zeitgeistpm/sdk.

The main JavaScript library for interacting with the Zeitgeist network.

Type definitions for the Zeitgeist network.

Types for the Zeigeist network.


Development Guide

We develop the JavaScript libraries inside of this monorepo and use Lerna as a tool to help us manage it. This repository uses TypeScript and we do not commit the built JavaScript files. Instead, the files will be generated when we publish the NPM packages, or if called manually by the developer.

Installing Dependencies

After cloning this monorepo to your local machine, you can use yarn to install the dependencies.

Compiling TypeScript

You can use the yarn compile script to compile the TypeScript packages. Inside of each package directory (ex. packages/cli) there will be a dist folder containing the built files. These files are used when publishing the packages to NPM, but are ignored when committing code. So any changes made to the compiled files will be ignored, and instead you should always do development in the TypeScript source.

Publishing to NPM

You will need access credentials to the zeitgeistpm organization on NPM. Once you have this, you are able to run the Lerna script lerna publish which will give you prompts for bumping up the version number and help you to publish a new version of the packages that have changed. By default, Lerna will only publish a new version for the packages that have been changed by checking the diff between the current files and the previous version.

Testing

Running the tests can be done in two ways:

  • Using lerna run test will run the test script in each package. This is useful if you want to make sure all packages are passing the tests (for example, we run this script in the CI to make sure we don't introduce any regressions).
  • Using yarn test while located in the package you want to test. For example, if you want to test only the sdk package, you would first navigate to the package in cli (cd packages/sdk) and then run yarn test.

tools's People

Contributors

c410-f3r avatar lsaether avatar morkeltry avatar robiquet avatar ryuheimat avatar saboonikhil avatar sea212 avatar tvrtkom avatar whisker17 avatar yornaath avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

tools's Issues

Can there be clearer names for the SDK?

In order to promote a consistent and minimally ambiguous vocabulary to simplify the experience of users of both the SDK and the whole platform, I am proposing to make a major overhaul of the function and variable names used in the SDK and CLI, in line with the (Glossary)[https://docs.zeitgeist.pm/glossary] and the more specific Google Doc proposal on it.

Broadly speaking, any deprecated terminology will be only at the lowest possible level (ie usually the substrate code) until changed there too.
There may be some cases where this is not desirable, however, as the substrate function names are accessible through Apps, which could cause users confusion if they differ from the SDK namings doing substantially the same thing.

Classes:

rename the whole Swaps class to SwapPool, and instances of it to swapPool or pool.
rename classes to the singular (affects only Models -> Model) and their and their filenames consistently either to the singular or plural (affects either market.ts or swaps.ts)

Methods:

getXxx and fetchXxx are used synonymously. Use getXxx as it is shorter.
Retain use of 'get' where retrieval involves an asynchronous request.
Remove redundant words from names.

Models

getAllMarketIds

(keep 'All' to imply analogy with getAllMarkets)

getAllMarkets

(keep 'All' as a simple plural may be too short to be an intuitive differentiator)

createNewMarket -> createMarket

(keep 'create' not 'new', as 'new' alone could imply that the new market will be returned. Keep 'market', as the class deals with more than just markets)

createNewCategoricalMarket -> createCategoricalMarket
createNewScalarMarket -> createScalarMarket
fetchMarketData-> getMarketData

(keep 'data' as it is data being returned, not the instance of the market)

fetchDisputes -> getDisputes
fetchPoolData-> getPool

(same name for Market.getPool as for SwapPool.getPool makes clear they do the same thing (although the method on Market requires a parameter, in order to specify the swap pool)

assetSpotPricesInZtg ->getAllPricesInZtg

(use all to differentiate from Market.getPricesInZtg / Market.assetSpotPricesInZtg

indexTransferRecipients

(keep name - this function does more than this, but the function will nt be relied upoj in it's current form and can be renamed later to better reflect the functionality of its future purpose)

Market

filterMarketData

(Keep 'market' as it is marketData that is being filtered.

deploySwapPool -> deployPool for consistency with getPool etc.
assetSpotPricesInZtg -> getPricesInZtg
buyCompleteSet

(keep name to match sellCompleteSet even though other verbs could be more appropriate)

sellCompleteSet

(keep name since there is no more intuitive verb which is accurate)

reportOutcome -> report

('report' is unambiguous and matches dispute. This will clash with the class field report, which is an ambiguous name and should be renamed (see below))

redeemShares -> redeemOutcomeAssets

(I would welcome a better phrase which makes clear both that only outcome assets are affected, and also implies finality. 'redeem' alone feels unituitive)

cancelAdvised -> cancelCreateMarket

(makes clear the relation to createMarket. An alternative would be -> cancel. Unclarity about the circumstances in which a market can be cancelled could be resolved with an error message, or param name)

Swaps/ swapPool

getSpotPrice consider -> getPrice

('price' is no more ambiguous than 'spot price' in this context)

assetSpotPricesInZtg -> getPricesInZtg
fetchPoolSpotPricesFromBlockNumbers -> getPricesFromBlockNumbers

('pool' is redundant as the method is on the SwapPool class. I cannot think of a shorter way to convey 'from block numbers')

fetchPoolSpotPrices -> getPriceMany

(don't pluralise price - 'prices' has been to used to mean prices of multiple assets at the same block. Otherwise, retain name as similar as possible to getPrice. In future these should be wrapped by a function which calls the correct method whether a single block, an array or none at all is passed.

sharesId -> getAssetTypeName

('shares' is deprecated; 'Id' is deprecated for this purpose. 'asset type' would be misleading since no type is returned, only the type's name.

accountId -> getAddress

('Id' is redundant. I would welcome suggestions on how to concisely convey that the Address returned is that of the swap pool rather than anything associated)

joinPool -> join

'join' is in the glossary and so should be unabmiguous in its meaning. The method will usually be called as something like pool.join(.... Confusion with Array.join seems unlikely.

poolJoinWithExactPoolAmount -> joinToReceiveExactLPTokenAmount

('pool' is inaccurate. 'receive' is more specific than 'with')

poolJoinWithExactAssetAmount -> joinToSpendExactAssetAmount
exitPool -> exit (confusion with other exits is unlikely, but the word 'leave' may be clearer, if we were to start using 'leave' over 'exit' when speaking in other contexts - needs discussion!)
poolExitWithExactAssetAmount -> exitToReceiveExactAssetAmount
poolExitWithExactPoolAmount ->exitToSpendExactLPTokenAmount

('remove', or even 'with' would be more accurate, but 'spend' makes clear analogy with joinToSpendExactAssetAmount. Improvements welcome)

swapExactAmountIn -> swapToSpendExactAmount

('exact amount' is ambiguous, since the natural reading would be for it to refer to both sides of the swap. 'In' and 'out' help only indirectly with that as they only indirectly specify which of the assets will be exact.

swapExactAmountOut -> swapToReceiveExactAmount

Class fields

Market

report -> reportedOutcome

(clearer, does not clash with proposed method report. Analogous with resolved_outcome. Could also use outcome, though that could cause confusion as 'outcome' is sometimes used to maen 'outcome asset' or 'outcome token'.

Swaps/ swapPool

weights/ totalWeight

...are confusing here, as weight is used as a parameter to mean relative weights, but here they appear to be absolute. Any suggestions for a more intuiuitve word? (alternatively, since substrate uses 'weight' as an absolute, maybe the weights param should be more explicitly relative?)

Add sanity metadata checks to SDK

On two levels:
1 - metadata may not be syntactically valid;
2 - there is currently no input or output sanity check against metadata which makes no sense in the context (eg scalar market may have categories)

See #59

Why is MarketId not camelcase?

marketId?: number;
endpoint: string;
};
const getShareBalances = async (opts: Options): Promise<void> => {
//@ts-ignore
const { addressOrSeed, seed, MarketId, endpoint } = opts;
const assets: any = ["ztg"];
let address, signer;
// this is crazy and I don't understand it :/
//@ts-ignore
const marketId = opts.marketId || MarketId;

I was unable to get commander to pass marketId as camelcased in this one specific case.
Could not resolve at the time, so I have made this odd hack.
I thought I had tried all the possible reasons, but obviously have missed something.
Look again at it with new eyes!

SDK Documentation

We need to set up a good documentation workflow.

We should have two sets of docs:

  • JSDoc based documentation, generated from new releases.
  • Higher level usage docs for developers using the SDK.

For the JSDocs we will need to ensure there is high quality documentation strings placed on all external functions. Ideally, a developer should never need to read the code to understand the interface of a function or what it does.

market end ambiguity

Market end can be either block number or a timestamp, and for that reason on front-end app we have utility function that calculates real end timestamp:

  if (`${market.end}`.length >= 13) {
    // assuming end is timestamp
    return market.end;
  }
  const diffInMS = 6000 * (market.end - blockNumber);
  return blockTimestamp + diffInMS;

I'd like to add this to sdk to remove a need to calculate it for each market. This has become more problematic since we started implementig sorting and filtering of markets on index page of the app.

Basically i suggest to either make market.end itself be a timestamp rather than a timestamp or a block number, or to add one more field market.endTimestamp representing end date timestamp.

Otherwise we would need to make a proxy market object for each market gotten from sdk.

Figure out a good way to do mocking in tests

Right now tests rely on the fact that there is some testnet data to play around with.

Instead, we should mock the data to ensure that the libraries work even across restarts of Battery Park.

Need better events on swap pallet.

We need to implement better events on swap pallet so developers who will use our SDK would get better data through optional or opinionated callbacks.

Create a consistent and explanatory schema for error reporting in SDK

Currently, CLI/ SDK reports errors in at least four different ways to the user:

Unhandled Promise Rejection, with error type & message

The most disconcerting for the user!
Only example found:

2021-04-29 10:42:02        RPC-CORE: submitAndWatchExtrinsic(extrinsic: Extrinsic): ExtrinsicStatus:: 1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low
2021-04-29 10:42:02             DRR: Error: 1010: Invalid Transaction: Inability to pay some fees , e.g. account balance too low

Apparently thrown from @polkadot/rpc-provider/
Error is caught but interruption prevents unsub being called (so program hangs)

Errors thrown by SDK, with error message

These look appropriate for now
(but also

Error: Market with market id 1 does not exist. (ie rejected or cancelled)

ExtrinsicFailed reported through SDK, with {module, index} populated

This could be improved by SDK having an index of{module, index} -> Error

    ' {"applyExtrinsic":1}: system.ExtrinsicFailed::("index":3,"error":2 ...

The format perhaps should be merged with that of SDK errors?

ExtrinsicFailed reported through SDK, with {module, index} incomplete

    ' {"applyExtrinsic":1}: system.ExtrinsicFailed:: [{"other":null} .... 

Need to diagnose what these signify :/
(this one occurred attempting to cancel_market, but the market was previously approved)

My network node id is declared as a variable but it's not used when docker run

I've generated a key for a permanent node id on WSL but my Local node identity is another one.

I used this docker image : fb127223ea8990bb27819dbbb9b15a46d7ffea73

Variables seems to be OK :

$ZEITGEIST_KEY_PATH=/root/.zeitgeist
$ZEITGEIST_KEY_NAME=12D...........bu

I would like to know how to configure a specific node ID for my node ?
I'm not getting good results with this procedure: https://docs.zeitgeist.pm/battery-park

Thanks

createNewMarket arguments

If createNewMarket function gets changed in future please consider using options object instead of individual arguments:

e.g. something like createNewMarket(signer, title, options) instead of createNewMarket([endless list of arguments]).

investigate inconsistency in api consumption of `Asset`

passing incorrect params when Swaps.getSpotPrice expects only Asset
can throw an error where createType is exepcting lowercased Asset properties

RPC-CORE: getSpotPrice(pool_id: u128, asset_in: Asset, asset_out: Asset, at?: Hash): SerdeWrapper:: createType(Asset):: Cannot map Enum JSON, unable to find '[6,0]' in categoricaloutcome, scalaroutcome, combinatorialoutcome, poolshare, ztg
Error: createType(Asset):: Cannot map Enum JSON, unable to find '[6,0]' in categoricaloutcome, scalaroutcome, combinatorialoutcome, poolshare, ztg

but
(with Swaps.getSpotPrice modified to accept Asset | string, passing string to current version of AssetIdFromString (which yields Asset-like object)
the same can throw an error where some other part of SerdeWrapper is expecting UpperCased Asset properties.

RPC-CORE: getSpotPrice(pool_id: u128, asset_in: Asset, asset_out: Asset, at?: Hash): SerdeWrapper:: -32602: Invalid params: unknown variant `ztg`, expected one of `CategoricalOutcome`, `ScalarOutcome`, `CombinatorialOutcome`, `PoolShare`, `Ztg`.
Error: -32602: Invalid params: unknown variant `ztg`, expected one of `CategoricalOutcome`, `ScalarOutcome`, `CombinatorialOutcome`, `PoolShare`, `Ztg`.

indexWinners script gets dropped by remote peer and doesn't capture results

At some point the indexWinners script gets dropped from the connection to the RPC node and exits without capturing results:

2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        RPC-CORE: getBlock(hash?: BlockHash): SignedBlock:: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
2021-05-16 18:50:17        API/INIT: Health keepalive check failed: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
Oops at: 1621183817349
Error: disconnected from wss://bp-rpc-1.zeitgeist.pm: 1006:: Connection dropped by remote peer.
    at W3CWebSocket.value [as onclose] (/Users/logansaether/Code/zeitgeistpm/tools/node_modules/@polkadot/rpc-provider/ws/index.cjs:176:23)
    at W3CWebSocket._dispatchEvent [as dispatchEvent] (/Users/logansaether/Code/zeitgeistpm/tools/node_modules/yaeti/lib/EventTarget.js:107:17)
    at W3CWebSocket.onClose (/Users/logansaether/Code/zeitgeistpm/tools/node_modules/websocket/lib/W3CWebSocket.js:228:10)
    at WebSocketConnection.<anonymous> (/Users/logansaether/Code/zeitgeistpm/tools/node_modules/websocket/lib/W3CWebSocket.js:201:17)
    at WebSocketConnection.emit (events.js:315:20)
    at WebSocketConnection.EventEmitter.emit (domain.js:467:12)
    at WebSocketConnection.handleSocketClose (/Users/logansaether/Code/zeitgeistpm/tools/node_modules/websocket/lib/WebSocketConnection.js:389:14)
    at TLSSocket.emit (events.js:327:22)
    at TLSSocket.EventEmitter.emit (domain.js:467:12)
    at net.js:673:12
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

It should be able to gracefully handle connection being dropped and either capture partial results, or wait and attempt a reconnection to finish execution.

[monorepo] Release schedule and checklists

We need to start having regular, stable releases of the SDK, CLI, and other libraries in this monorepo. If we use the CI, we can just automate releases whenever something is merged to main. It would also be nice to have preview releases made from PRs, since we can test new features without needing to merge to main.

  • Decide on how releases should be made, at what frequency, and how.
  • Add CI scripts to help with releases using lerna.

Investigate Apps type errors (`Option<Market>` returned from prediction_markets::markets)

result in Apps;

impossible result in CLI

Apps:

Fresh, not locally cached, reload of https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fbp-rpc.zeitgeist.pm#/chainstate
contains:

types:"{"Asset":{"_enum":{"CategoricalOutcome":"(MarketId, CategoryIndex)","ScalarOutcome":"(MarketId, ScalarPosition)","CombinatorialOutcome":"","PoolShare":"u128","Ztg":""}},"CurrencyIdOf":"Asset","CurrencyId":"Asset","CategoryIndex":"u16","RangeInclusive":"(u128, u128)","MarketType":{"_enum":{"Categorical":"u16","Scalar":"RangeInclusive"}},"Outcome":{"_enum":{"Categorical":"u16","Scalar":"u128"}},"Market":{"creator":"AccountId","creation":"MarketCreation","creator_fee":"u8","oracle":"AccountId","end":"MarketEnd","metadata":"Vec<u8>","market_type":"MarketType","status":"MarketStatus","report":"Option<Report>","resolved_outcome":"Outcome"}}"
``
Getting prediction_markets::markets (3)

logs error:

2021-05-06 14:36:08 DRR: Unable to decode storage predictionMarkets.markets: entry 0:: createType(Option):: Option:: Decoded input doesn't match input, received 0x0120c762c7f3b12ae691d3a444e80fc5ec7c89098bb820a934c71ede8bc53d54…0000000000000000000000000008000000000000000000000000000000010000 (159 bytes), created 0x0120c762c7f3b12ae691d3a444e80fc5ec7c89098bb820a934c71ede8bc53d54…0000000000000000000000080000000000000000000000000000000100000000 (161 bytes)


##### CLI:

Running CLI locally with `"name": "@zeitgeistpm/types", "version": "0.1.50"`,
and "@zeitgeistpm/type-defs",  "version": "0.1.50"`, which contains:

export default {
rpc: {
predictionMarkets: {
marketOutcomeShareId: {
description: "Get the market outcome share identifier.",
params: [
{
name: "market_id",
type: "MarketId",
},
{
name: "outcome",
type: "u16",
},
{
name: "at",
type: "Hash",
isOptional: true,
},
],
type: "Hash",
},
},
},
types: {
MarketCreation: {
_enum: ["Permissionless", "Advised"],
},
MarketEnd: {
_enum: {
Block: "BlockNumber",
Timestamp: "u64",
},
},
MarketId: "u128",
MarketType: {
_enum: {
Categorical: "u16",
Scalar: "(u128, u128)"
}
},
MarketStatus: {
_enum: [
"Proposed",
"Active",
"Suspended",
"Closed",
"Reported",
"Disputed",
"Resolved",
],
},
Market: {
creator: "AccountId",
creation: "MarketCreation",
creator_fee: "u8",
oracle: "AccountId",
end: "MarketEnd",
metadata: "Vec",
market_type: "MarketType",
market_status: "MarketStatus",
report: "Option",
resolved_outcome: "Option",
},
Outcome: {
_enum : {
Categorical: "u16",
Scalar: "u128"
}
},
Report: {
at: "BlockNumber",
by: "AccountId",
outcome: "Outcome",
},
MarketDispute: {
at: "BlockNumber",
by: "AccountId",
outcome: "Outcome",
},
},
};


logs the result:

wss://bp-rpc.zeitgeist.pm initialised in 1676 ms.
{
"creator": "5Cogct4f5ThQZJBVywY2a5GKW8LU3hvwdm8dqjLRikzpshMt",
"creation": "Permissionless",
"creatorFee": 0,
"oracle": "5Cogct4f5ThQZJBVywY2a5GKW8LU3hvwdm8dqjLRikzpshMt",
"end": {
"block": 2500
},
"metadata": "0x516d56787175647571333679666d4c4658364242386734316d4363593841347452516a337032445a703947434e66",
"marketType": {
"scalar": [
0,
8
]
},
"marketStatus": "Active",
"report": null,
"categories": [
"Acala",
"Plasm",
"Edgeware",
"Maker",
"Shyft",
"Mina",
"Cere"
],
"resolvedOutcome": null,
"marketId": 3,
"title": "Parachain slot (test #1)",
"description": "Who will win?",
"metadataString": "QmVxquduq36yfmLFX6BB8g41mCcY8A4tRQj3p2DZp9GCNf",
"outcomeAssets": [
{
"scalarOutcome": [
3,
"Long"
]
},
{
"scalarOutcome": [
3,
"Short"
]
}
]
}

ie a `scalar` market containing `categories` 

Make "opinionated callbacks" optional

Right now we have two ways that we handle the callbacks that we get back from making a transaction using the upstream Polkadot-JS API library:

One way is that we define an optionated callback which will resolve the promise with a value that we provide. This is nice because we are able to select only the necessary information that needs to be returned from this function and return it for the developer.

async sellCompleteSet(
signer: KeyringPairOrExtSigner,
amount: number
): Promise<boolean> {
const callback = (
result: ISubmittableResult,
_resolve: (value: boolean | PromiseLike<boolean>) => void,
_unsub: () => void
) => {
const { status } = result;
if (status.isInBlock) {
_unsub();
}
_resolve(true);
};
return new Promise(async (resolve) => {
if (isExtSigner(signer)) {
const unsub = await this.api.tx.predictionMarkets
.sellCompleteSet(this.marketId, amount)
.signAndSend(signer.address, { signer: signer.signer }, (result) =>
callback(result, resolve, unsub)
);
} else {
const unsub = await this.api.tx.predictionMarkets
.sellCompleteSet(this.marketId, amount)
.signAndSend(signer, (result) => callback(result, resolve, unsub));
}
});
}

However we also want to allow developer to access the lower level callback from the API if they need to, so we provide callback as an optional parameter. For example:

joinPool = async (
signer: KeyringPairOrExtSigner,
poolAmountOut: string,
maxAmountsIn: string[],
callback?: (result: ISubmittableResult, unsub: () => void) => void
): Promise<boolean> => {
const tx = this.api.tx.swaps.joinPool(
this.poolId,
poolAmountOut,
maxAmountsIn
);
if (isExtSigner(signer)) {
const unsub = await tx.signAndSend(
signer.address,
{ signer: signer.signer },
(result) => {
callback(result, unsub);
}
);
} else {
const unsub = await tx.signAndSend(signer, (result) => {
callback(result, unsub);
});
}
return true;
};

We should make it so that the callback parameter is available on all of our functions if they are necessary, but if they aren't provided we use our own "opinionated callback" that returns the information we think will be useful.

Standardise type of numerical CLI parameters

e.g. marketId.
They are sometimes string, sometimes number.

Currently strings are converted with Number(). Check that changing type to number does not miss edge cases (eg missing param).

`joinPoolMultiFunc`, `exitPoolMultiFunc`

Test edge cases and provide endpoint corresponding to the available functions on the swaps api:

poolJoinWithExactAssetAmount
poolJoinWithExactPoolAmount

and implement equivalents for exitPool.

Rename
joinPoolMultifunc to joinPool
(also note, the current function name is not properly camelcased!)

Test success and failure conditions of

redeemShares; joinPoolMulitifunc; exitPool; swapExactAmountIn; swapExactAmountOut all had a bug where any response from api was interpreted as success and they resolved the callback promise with true.

Instead, now all events from the isInBlock block are parsed and method == "ExtrinsicSuccess" resolves true method == "ExtrinsicFailed" resolves false.

Need to test whether ExtrinsicFailed is an achievable result for each method, and decide whether more intelligent resolve value than true may be appropriate.

pin down undefined behaviour in @polkadot/api

(lower priority than it sounds ;) )

fetchMarketData should never receive no or undefined marketId, however during debugging, it did, resulting in
the marketId parameter to api.query.predictionMarkets.markets(marketId) being undefined.

api did not throw but provided a trivial response.
May be worth investigating...

Use chain metadata to populate error table on API initilaization

The mapping of pallet index and error index to documentation is available in the metadata.

You can test this out by going to https://polkadot.js.org/apps/#/js and pasting this snippet:

const metadata = await api.rpc.state.getMetadata();
const inner = metadata.get('metadata');
 for (const module of inner.toJSON().v12.modules) {
    const { name, errors, index } = module;
    // skip any that don't have errors
    if (!errors.length) continue;
    errors.map((error, errorIndex) => {
      const { name: errorName, documentation } = error;
      console.log(`${name} (${index}) |  ${errorName} (${errorIndex}) | ${documentation}`);
    });
  }

Using the metadata we can populate an error table on initialization then display the documentation to the user when they encounter an error.

Side quest: We should also use this code snippet to populate a MarkDown page that can hosted in the docs that we can point people to when they have errors.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.