docs: api changes
This commit is contained in:
507
README.md
507
README.md
@@ -6,85 +6,42 @@ Warp SDK is the implementation of the SmartWeave [Protocol](./docs/SMARTWEAVE_PR
|
||||
|
||||
It works in both web and Node.js environment (requires Node.js 16.5+).
|
||||
|
||||
It has been built with performance (e.g. caching at multiple layers, Arweave calls optimization)
|
||||
and modularity (e.g. ability to use different types of caches, imported from external libraries) in mind.
|
||||
|
||||
We're already using the new SDK on production, both in our webapp and nodes.
|
||||
However, if you'd like to use it in production as well, please contact us on [discord](https://discord.com/invite/PVxBZKFr46) to ensure a smooth transition and get help with testing.
|
||||
|
||||
To further improve contract state evaluation time, one can additionally use AWS CloudFront based Arweave cache described [here](https://github.com/redstone-finance/warp/blob/main/docs/CACHE.md).
|
||||
If you are interested in the main assumptions for Warp ecosystem as well as its key features go visit [our website](https://warp.cc).
|
||||
|
||||
- [Architecture](#architecture)
|
||||
- [State evaluation diagram](#state-evaluation-diagram)
|
||||
- [Warp transaction lifecycle](#warp-transaction-lifecycle)
|
||||
- [Development](#development)
|
||||
- [Installation](#installation)
|
||||
- [Using npm](#using-npm)
|
||||
- [Using yarn](#using-yarn)
|
||||
- [Import](#import)
|
||||
- [Using the Warp Gateway](#using-the-warp-gateway)
|
||||
- [WarpFactory](#warpfactory)
|
||||
- [forLocal](#forlocal)
|
||||
- [forTestnet](#fortestnet)
|
||||
- [forMainnet](#formainnet)
|
||||
- [custom](#custom)
|
||||
- [WarpEnvironment](#warpenvironment)
|
||||
- [Deployment](#deployment)
|
||||
- [Contract methods](#contract-methods)
|
||||
- [`connect`](#connect)
|
||||
- [`setEvaluationOptions`](#setevaluationoptions)
|
||||
- [`readState`](#readstate)
|
||||
- [`viewState`](#viewstate)
|
||||
- [`dryWrite`](#drywrite)
|
||||
- [`writeInteraction`](#writeinteraction)
|
||||
- [`evolve`](#evolve)
|
||||
- [WASM](#wasm)
|
||||
- [VM2](#vm2)
|
||||
- [Internal writes](#internal-writes)
|
||||
- [UnsafeClient](#unsafeclient)
|
||||
- [Performance - best practices](#performance---best-practices)
|
||||
- [Examples](#examples)
|
||||
- [Migration guide](#migration-guide)
|
||||
|
||||
## Architecture
|
||||
|
||||
Warp SDK consists of main 3 layers:
|
||||
|
||||
<img src="https://smartweave.redstone.finance/assets/img/illustrations/architecture.svg" height='50%' width='50%'>
|
||||
|
||||
1. The `Core Protocol` layer is the implementation of the original SmartWeave protocol and is responsible for communication with the SmartWeave smart contracts deployed on Arweave. It consists of 5 modules:
|
||||
1. `Interactions Loader` - this module is responsible for loading from Arweave all the interaction transactions registered
|
||||
for given contract.
|
||||
2. `Interactions Sorter` - responsible for sorting the interactions according to the protocol specification. This is crucial operation for the deterministic contract state evaluation.
|
||||
3. `Definition Loader` - this module loads all the data related to the given SmartWeave contract - its source code, initial state, etc.
|
||||
4. `Executor Factory` - this module is responsible for creating "handles" to the SmartWeave contract. These handles are then used by the SDK to call SmartWeave contract methods.
|
||||
5. `State Evaluator` - this module is responsible for evaluating SmartWeave contract state up to the requested block height.
|
||||
2. The `Caching` layer - is build on top of the `Core Protocol` layer and allows caching results of each of the `Core Protocol` modules separately.
|
||||
The main interfaces of this layer are the:
|
||||
1. `WarpCache` - simple key-value cache, useful for modules like `Definition Loader`
|
||||
2. `SortKeyCache` - a transaction sort key aware cache, crucial for modules like `Interactions Loader` and `State Evaluator`.
|
||||
These interfaces - used in conjunction with cache-aware versions of the core modules (like `CacheableContractInteractionsLoader` or `CacheableStateEvaluator`)
|
||||
allow to greatly improve performance and Warp contract's state evaluation time - especially for contracts that heavily interact with other contracts.
|
||||
3. The `Extensions` layer - includes everything that can be built on top of the core SDK - including Command Line Interface, Debugging tools, different logging implementations,
|
||||
so called "dry-runs" (i.e. actions that allow to quickly verify the result of given contract interaction - without writing anything on Arweave).
|
||||
|
||||
This modular architecture has several advantages:
|
||||
|
||||
1. Each module can be separately tested and developed.
|
||||
2. The Warp client can be customized depending on user needs (e.g. different type of caches for web and node environment)
|
||||
3. It makes it easier to add new features on top of the core protocol - without the risk of breaking the functionality of the core layer.
|
||||
|
||||
## State evaluation diagram
|
||||
|
||||

|
||||
|
||||
In order to perform contract state evaluation (at given block height), SDK performs certain operations.
|
||||
The diagram above and description assume the most basic “mem-cached” SDK client.
|
||||
|
||||
1. Users who are interacting with the contract, call the “readState” method.
|
||||
2. Interactions Loader and Contract Definition Loader modules are then called in parallel - to load all the data required for state evaluation. Both Interactions Loader and Contract Definition Loader first check its corresponding cache whether data is already loaded - and load from the gateway (either Warp gateway or Arweave one) only the missing part.
|
||||
3. With interactions and contract definition loaded - Executor Factory creates a handle to the Warp contract main function (or loads it from its own cache)
|
||||
4. With all the interactions and a contract handle - the State Evaluator evaluates the state from the lastly cached value - and returns the result to User.
|
||||
|
||||
## Warp transaction lifecycle
|
||||
|
||||

|
||||
|
||||
Warp SDK is just part of the whole Warp smart contracts platform. It makes transactions processing and evaluation easy and effective.
|
||||
|
||||
1. Our Sequencer assigns order to SmartWeave interactions, taking into account sequencer’s timestamp, current Arweave network block height and is salted with sequencer’s key.
|
||||
|
||||
2. Interactions are then packed by Bundlr which guarantees transactions finality and data upload reliability.
|
||||
The ability to directly process rich content
|
||||
|
||||
3. Transactions are stored on Arweave where they are available for querying.
|
||||
|
||||
4. The key component for the lazy-evaluation nature of SmartWeave protocol is fast and reliable interaction loading. Thanks to our gateway we guarantee loading transactions in seconds in a reliable way - it has built-in protection against forks and corrupted transactions. Our gateway enables fast queries and efficient filtering of interactions, which in effect greatly reduces state evaluation time.
|
||||
|
||||
5. Lastly, transactions can be evaluated either by our SDK or the evaluation can be delegated to a distribution execution network - a dedicated network of nodes (DEN). Multi-node executors network listens to incoming transactions and automatically update contract state.
|
||||
- [Migrations](#migrations)
|
||||
- [Old factories to WarpFactory](#old-factories-to-warpfactory)
|
||||
- [Sqlite to LevelDB](#sqlite-to-leveldb)
|
||||
- [Examples](#examples)
|
||||
- [Warp transaction lifecycle](#warp-transaction-lifecycle)
|
||||
|
||||
## Development
|
||||
|
||||
@@ -107,6 +64,11 @@ SDK requires node.js version 16.5+.
|
||||
|
||||
You can import the full API or individual modules.
|
||||
|
||||
The SDK is available in both the ESM and CJS format - to make it possible for web bundlers (like webpack) to effectively
|
||||
perform tree-shaking.
|
||||
|
||||
**ESM**
|
||||
|
||||
```typescript
|
||||
import * as WarpSdk from 'warp-contracts';
|
||||
```
|
||||
@@ -115,8 +77,15 @@ import * as WarpSdk from 'warp-contracts';
|
||||
import { Warp, Contract, ... } from 'warp-contracts'
|
||||
```
|
||||
|
||||
The SDK is available in both the ESM and CJS format - to make it possible for web bundlers (like webpack) to effectively
|
||||
perform tree-shaking.
|
||||
**CJS**
|
||||
|
||||
```javascript
|
||||
const Warp = require('warp-contracts');
|
||||
```
|
||||
|
||||
```javascript
|
||||
const { Warp, Contract, ... } = require('warp-contracts');
|
||||
```
|
||||
|
||||
#### Using web bundles
|
||||
|
||||
@@ -144,80 +113,158 @@ All exports are stored under `warp` global variable.
|
||||
</script>
|
||||
```
|
||||
|
||||
### Using the Warp Gateway
|
||||
### WarpFactory
|
||||
|
||||
```ts
|
||||
import {WarpFactory} from "./WarpFactory";
|
||||
To properly initialize Warp you can use one of three methods available in WarpFactory class which simplifies the process of creating Warp.
|
||||
|
||||
const warp = WarpFactory.warpGw(arweave);
|
||||
#### forLocal
|
||||
|
||||
Creates a Warp instance suitable for testing in a local environment.
|
||||
|
||||
```typescript
|
||||
warp = WarpFactory.forLocal();
|
||||
```
|
||||
|
||||
By default, the `{notCorrupted: true}` mode is used.
|
||||
Optionally - you can pass the second argument to the `warpGw` method that will determine the options for the Warp gateway.
|
||||
The options object has three fields:
|
||||
1. `confirmationStatus` - with default set to `{ notCorrupted: true }` - which returns all confirmed and non-yet processed/confirmed transactions.
|
||||
Other possible values are:
|
||||
- `{confirmed: true}` - returns only the confirmed transactions - keep in mind that transaction confirmation takes around 20-30 minutes.
|
||||
- `null` - compatible with how the Arweave Gateway GQL endpoint works - returns
|
||||
all the interactions. There is a risk of returning [corrupted transactions](https://github.com/redstone-finance/redstone-sw-gateway#corrupted-transactions).
|
||||
2. `source` - with default set to `null` - which loads interactions registered both directly on Arweave and through Warp Sequencer.
|
||||
Other possible values are: `SourceType.ARWEAVE` and `SourceType.WARP_SEQUENCER`
|
||||
3. `address` - the gateway address, by default set to `WARP_GW_URL`
|
||||
Default parameters (each of them can be adjusted to your needs):
|
||||
|
||||
E.g.:
|
||||
```ts
|
||||
import {defaultWarpGwOptions, WarpFactory} from "./WarpFactory";
|
||||
1. `port` - set to `1984`
|
||||
2. `arweave` - Arweave initialized with `host` set to `localhost`, `port` set to default `port` from p. 1 and `protocol` set to `http`
|
||||
3. `cacheOptions` - optional cache options parameter, by default `inMemory` cache is set to `true`
|
||||
|
||||
const warp = WarpFactory.warpGw(arweave, {...defaultWarpGwOptions, confirmationStatus: { confirmed: true }});
|
||||
#### forTestnet
|
||||
|
||||
Creates a Warp instance suitable for testing with Warp testnet (https://testnet.redstone.tools/).
|
||||
|
||||
```typescript
|
||||
warp = WarpFactory.forTestnet();
|
||||
```
|
||||
|
||||
The Warp gateway is currently available under [https://gateway.redstone.finance](https://gateway.redstone.finance) url.
|
||||
Full API reference is available [here](https://github.com/redstone-finance/redstone-sw-gateway#http-api-reference).
|
||||
Default parameters (each of them can be adjusted to your needs):
|
||||
|
||||
### Using the Arweave gateway
|
||||
1. `arweave` - Arweave initialized with `host` set to `testnet.redstone.tools`, `port` set to `443` and `protocol` set to `https`
|
||||
2. `cacheOptions` - optional cache options parameter, by default `inMemory` cache is set to `false`
|
||||
|
||||
```ts
|
||||
import {WarpFactory} from "./WarpFactory";
|
||||
#### forMainnet
|
||||
|
||||
const warp = WarpFactory.arweaveGw(arweave);
|
||||
Creates a Warp instance suitable for use with mainnet.
|
||||
By default, the Warp gateway (https://github.com/warp-contracts/gateway#warp-gateway) is being used for:
|
||||
|
||||
1. deploying contracts
|
||||
2. writing new transactions through Warp Sequencer
|
||||
3. loading contract interactions
|
||||
|
||||
```typescript
|
||||
warp = WarpFactory.forMainnet();
|
||||
```
|
||||
|
||||
More examples can be found [here](https://github.com/redstone-finance/redstone-smartcontracts-examples/blob/main/src/redstone-gateway-example.ts).
|
||||
Default parameters (each of them can be adjusted to your needs):
|
||||
|
||||
### Testing on ArLocal
|
||||
All our integration tests are using ArLocal and we strongly suggest using it for testing your
|
||||
own contracts.
|
||||
In order to make the testing easier, a dedicated factory method has been added:
|
||||
1. `cacheOptions` - optional cache options parameter, by default `inMemory` cache is set to `false`
|
||||
2. `useArweaveGw` - defaults to `false`, if set to `true` - `arweave.net` gateway is used for deploying contracts, writing and loading interactions
|
||||
3. `arweave` - Arweave initialized with `host` set to `arweave.net`, `port` set to `443` and `protocol` set to `https`
|
||||
|
||||
```ts
|
||||
import {WarpFactory} from "./WarpFactory";
|
||||
#### custom
|
||||
|
||||
const warp = WarpFactory.forTesting(arweave);
|
||||
Allows to fully customize `Warp` instance.
|
||||
|
||||
```typescript
|
||||
warp = WarpFactory.custom(
|
||||
arweave,
|
||||
{
|
||||
...defaultCacheOptions,
|
||||
inMemory: true
|
||||
},
|
||||
'testnet'
|
||||
)
|
||||
.useArweaveGateway()
|
||||
.setInteractionsLoader(loader)
|
||||
.build();
|
||||
```
|
||||
|
||||
It creates a `Warp` instance that can be used with the ArLocal.
|
||||
Additionally, it is using the in-memory implementation of the LevelDB
|
||||
([memory-level](https://www.npmjs.com/package/memory-level)) - so that manually cleaning
|
||||
the cache storage is not required.
|
||||
No default paramters are provided, these are the parameters that you can adjust to your needs:
|
||||
|
||||
1. `arweave` - initializes Arweave
|
||||
2. `cacheOptions` - optional cache options parameter, by default `inMemory` cache is set to `true`
|
||||
3. `environment` - environment in which Warp will be initialized
|
||||
|
||||
`custom` method returns preconfigured instance of `Warp` - `WarpBuilder` which can be customized, the configuration is finished with `build` method.
|
||||
|
||||
#### WarpEnvironment
|
||||
|
||||
`WarpEnvironment` is a helper type which can be used in scripts etc. to determine in which environment Warp has been initialized.
|
||||
|
||||
Possible options:
|
||||
|
||||
```typescript
|
||||
'local' | 'testnet' | 'mainnet' | 'custom';
|
||||
```
|
||||
|
||||
```typescript
|
||||
if (warp.environment == 'mainnet') {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Deployment
|
||||
|
||||
#### deploy
|
||||
|
||||
Deploys contract to Arweave. By default deployment transaction is bundled and posted on Arweave using Warp Sequencer. If you want to deploy your contract directly to Arweave - disable bundling by setting `disableBundling` to `true`.
|
||||
|
||||
```typescript
|
||||
async function deploy(contractData: ContractData, disableBundling?: boolean): Promise<ContractDeploy>;
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```typescript
|
||||
const { contractTxId, srcTxId } = await warp.createContract.deploy({
|
||||
wallet,
|
||||
initState: initialState,
|
||||
data: { 'Content-Type': 'text/html', body: '<h1>HELLO WORLD</h1>' },
|
||||
src: contractSrc,
|
||||
tags
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### deployFromSourceTx
|
||||
|
||||
Deploys contract from source transaction. By default deployment transaction is bundled and posted on Arweave using Warp Sequencer. If you want to deploy your contract directly to Arweave - disable bundling by setting `disableBundling` to `true`.
|
||||
|
||||
```typescript
|
||||
async function deployFromSourceTx(
|
||||
contractData: FromSrcTxContractData,
|
||||
disableBundling?: boolean
|
||||
): Promise<ContractDeploy>;
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```typescript
|
||||
const { contractTxId, srcTxId } = await warp.createContract.deployFromSourceTx({
|
||||
wallet,
|
||||
initState: initialState,
|
||||
srcTxId: 'SRC_TX_ID'
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### Contract methods
|
||||
|
||||
- [`connect`](#connect)
|
||||
- [`setEvaluationOptions`](#setevaluationoptions)
|
||||
- [`readState`](#readstate)
|
||||
- [`viewState`](#viewstate)
|
||||
- [`writeInteraction`](#writeinteraction)
|
||||
- [`bundleInteraction`](#bundleInteraction)
|
||||
|
||||
#### `connect`
|
||||
|
||||
```typescript
|
||||
async function connect(wallet: ArWallet): Contract<State>;
|
||||
connect(signer: ArWallet | SigningFunction): Contract<State>;
|
||||
```
|
||||
|
||||
Allows to connect wallet to a contract. Connecting a wallet MAY be done before "viewState" (depending on contract implementation, ie. whether called contract's function required "caller" info) Connecting a wallet MUST be done before "writeInteraction".
|
||||
|
||||
- `wallet` a JWK object with private key or 'use_wallet' string.
|
||||
- `signer` - JWK object with private key, 'use_wallet' string or custom signing function.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
@@ -236,11 +283,7 @@ const contract = warp.contract('YOUR_CONTRACT_TX_ID').connect(jwk);
|
||||
function setEvaluationOptions(options: Partial<EvaluationOptions>): Contract<State>;
|
||||
```
|
||||
|
||||
Allows to set (EvaluationOptions)
|
||||
|
||||
- `options` the interaction input
|
||||
- `options.ignoreExceptions` enables exceptions ignoring
|
||||
- `options.waitForConfirmation` enables waiting for transaction confirmation
|
||||
Allows to set [EvaluationOptions](https://github.com/warp-contracts/warp/blob/main/src/core/modules/StateEvaluator.ts#L123) that will overwrite current configuration.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
@@ -260,15 +303,15 @@ const contract = warp.contract('YOUR_CONTRACT_TX_ID').setEvaluationOptions({
|
||||
|
||||
```typescript
|
||||
async function readState(
|
||||
blockHeight?: number,
|
||||
sortKeyOrBlockHeight?: string | number,
|
||||
currentTx?: { contractTxId: string; interactionTxId: string }[]
|
||||
): Promise<EvalStateResult<State>>;
|
||||
```
|
||||
|
||||
Returns state of the contract at required blockHeight. Similar to the `readContract` from the version 1.
|
||||
Returns state of the contract at required blockHeight or sortKey. Similar to the `readContract` from the version 1.
|
||||
|
||||
- `blockHeight` Block height for state
|
||||
- `currentTx` If specified, will be used as a current transaction
|
||||
- `sortKeyOrBlockHeight` - either a sortKey or block height at which the contract should be read
|
||||
- `currentTx` - if specified, will be used as a current transaction
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
@@ -343,17 +386,53 @@ const { result } = await contract.viewStateForTx<any, any>({
|
||||
|
||||
---
|
||||
|
||||
#### `dryWrite`
|
||||
|
||||
```typescript
|
||||
async function dryWrite<Input>(
|
||||
input: Input,
|
||||
caller?: string,
|
||||
tags?: Tags,
|
||||
transfer?: ArTransfer
|
||||
): Promise<InteractionResult<State, unknown>>;
|
||||
```
|
||||
|
||||
A dry-write operation on contract. It first loads the contract's state and then creates a "dummy" transaction and applies the given Input on top of the current contract's state.
|
||||
|
||||
- `input` - input to be applied on the current contract's state
|
||||
- `tags` - additional tags to be added to interaction transaction
|
||||
- `transfer` - additional transfer data to be associated with the "dummy" transaction
|
||||
- `caller` - an option to override the caller - if available, this value will overwrite the caller evaluated from the wallet connected to this contract.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```typescript
|
||||
const result = await contract.dryWrite({
|
||||
function: "NAME_OF_YOUR_FUNCTION",
|
||||
data: { ... }
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
#### `writeInteraction`
|
||||
|
||||
```typescript
|
||||
async function writeInteraction<Input>(input: Input, tags?: Tags, transfer?: ArTransfer): Promise<string>;
|
||||
async function writeInteraction<Input = unknown>(
|
||||
input: Input,
|
||||
options?: WriteInteractionOptions
|
||||
): Promise<WriteInteractionResponse | null>;
|
||||
```
|
||||
|
||||
Writes a new "interaction" transaction - ie. such transaction that stores input for the contract.
|
||||
|
||||
- `input` the interaction input
|
||||
- `tags` an array of tags with name/value as objects
|
||||
- `transfer` target and winstonQty for transfer
|
||||
- `options` - an object with some custom options (see [WriteInteractionOptions](https://github.com/warp-contracts/warp/blob/src/contract/Contract.ts#L46))
|
||||
|
||||
By default write interaction transactions are bundled and posted on Arweave using Warp Sequencer. If you want to post transactions directly to Arweave - disable bundling by setting `options.disableBundling` to `true`.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
@@ -367,6 +446,51 @@ const result = await contract.writeInteraction({
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
#### `evolve`
|
||||
|
||||
```typescript
|
||||
async function evolve(newSrcTxId: string, options?: WriteInteractionOptions): Promise<WriteInteractionResponse | null>;
|
||||
```
|
||||
|
||||
Allows to change contract's source code, without having to deploy a new contract. This method effectively evolves the contract to the source. This requires the `save` method to be called first and its transaction to be confirmed by the network.
|
||||
|
||||
- `newSrcTxId` - result of the `save` method call.
|
||||
- `options` - an object with some custom options (see [WriteInteractionOptions](https://github.com/warp-contracts/warp/blob/src/contract/Contract.ts#L46))
|
||||
|
||||
By default evolve interaction transactions are bundled and posted on Arweave using Warp Sequencer. If you want to post transactions directly to Arweave - disable bundling by setting `options.disableBundling` to `true`.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```typescript
|
||||
const result = await contract.evolve('srcTxId');
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### save
|
||||
|
||||
Allows to save contract source on Arweave. Currently, using bundler to save the source is not possible.
|
||||
|
||||
```typescript
|
||||
async function save(
|
||||
contractSource: SourceData,
|
||||
signer?: ArWallet | SigningFunction,
|
||||
useBundler?: boolean
|
||||
): Promise<string | null>;
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```typescript
|
||||
const newSrcTxId = await contract.save({ src: newSource });
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### WASM
|
||||
|
||||
WASM provides proper sandboxing ensuring execution environment isolation which guarantees security to the contracts execution. As for now - **Assemblyscript**, **Rust** and **Go** languages are supported. WASM contracts templates containing example PST contract implementation within tools for compiling contracts to WASM, testing, deploying (locally, on testnet and mainnet) and writing interactions are available in a [dedicated repository](https://github.com/redstone-finance/redstone-smartcontracts-wasm-templates).
|
||||
@@ -430,36 +554,101 @@ await SmartWeave.contracts.readContractState(action.input.contractId);
|
||||
|
||||
You can view some more examples in the [internal writes test directory](https://github.com/redstone-finance/redstone-smartcontracts/tree/main/src/__tests__/integration/internal-writes). If you would like to read whole specification and motivation which stands behind introducing internal writes feature, please read [following issue](https://github.com/redstone-finance/redstone-smartcontracts/issues/37).
|
||||
|
||||
### Performance - best practices
|
||||
### unsafeClient
|
||||
|
||||
In order to get the best performance on production environment (or while performing benchmarks ;-)), please follow these simple rules:
|
||||
`unsafeClient` is available to use on `Smartweave` global object. It gives access to whole `Arweave` instance.
|
||||
Example of usage:
|
||||
|
||||
1. Do NOT use the `TsLoggerFactory` - it is good for development, as it formats the logs nicely, but might slow down the state evaluation
|
||||
by a factor of 2 or 3 (depending on the logging level).
|
||||
2. Use `fatal` or `error` log level, e.g.:
|
||||
|
||||
```ts
|
||||
// configure the logging first
|
||||
LoggerFactory.INST.logLevel('fatal');
|
||||
// or
|
||||
LoggerFactory.INST.logLevel('error');
|
||||
|
||||
// then create an instance of smartweave sdk
|
||||
const warp = WarpFactory.memCached(arweave);
|
||||
```typescript
|
||||
const result = await SmartWeave.unsafeClient.transactions.getData('some_id);
|
||||
```
|
||||
|
||||
Logging on `info` or `debug` level is good for development, but turning it on globally might slow down the evaluation by a factor of 2.
|
||||
Keep in mind that you can fine tune the log level of each module separately. For example you can switch the `fatal` globally, but `debug`
|
||||
for the `ArweaveGatewayInteractionsLoader` (in order to verify the load times from Arweave GQL endpoint). The names of the modules are derived from the
|
||||
names of TypeScript classes, e.g.:
|
||||
However, we do not recommend using it as it can lead to non-deterministic results. Therefore, we do not support it by default in Warp. If you want to use it anyway, you need to explicitely set `EvaluationOptions.allowUnsafeClient` flag to `true`.
|
||||
|
||||
```ts
|
||||
// configure the logging first
|
||||
LoggerFactory.INST.logLevel('fatal');
|
||||
LoggerFactory.INST.logLevel('debug', 'ArweaveGatewayInteractionsLoader');
|
||||
### Cache
|
||||
|
||||
// then create an instance of smartweave sdk
|
||||
const smartweave = SmartWeaveFactory.memCached(arweave);
|
||||
Warp uses [LevelDB](https://github.com/google/leveldb) to cache the state. During the state evaluation, state is then evaluated only for which the state hasn't been evaluated yet. State is being cached per transaction and not per block height. The reason behind that caching per block height is not enough if multiple interactions are at the same height and two contracts interact with each other. The LevelDB is a lexicographically sorted key-value database - so it's ideal for this use case - as it simplifies cache look-ups (e.g. lastly stored value or value "lower-or-equal" than given sortKey). The cache for contracts are implemented as [sub-levels](https://www.npmjs.com/package/level#sublevel--dbsublevelname-options). The default location for the node.js cache is ./cache/warp.
|
||||
|
||||
In the browser environment Warp uses [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) to cache the state - it's a low-level API for client-side storage.
|
||||
The default name for the browser IndexedDB cache is warp-cache.
|
||||
|
||||
In order to reduce the cache size, the oldest entries are automatically pruned.
|
||||
|
||||
It is possible to use the in-memory cache instead by setting `cacheOptions.inMemory` to `true` while initializing Warp. `inMemory` cache is used by default in local environment.
|
||||
|
||||
### Migrations
|
||||
|
||||
#### old factories to WarpFactory
|
||||
|
||||
1. Mainnet
|
||||
This is how you would intiialize Warp 'the old way':
|
||||
|
||||
```typescript
|
||||
const warp = WarpNodeFactory.memCachedBased(arweave).build();
|
||||
```
|
||||
|
||||
or - for browser:
|
||||
|
||||
```typescript
|
||||
const warp = WarpNodeFactory.memCachedBased(arweave).build();
|
||||
```
|
||||
|
||||
Now, you just need to initialize it like so:
|
||||
|
||||
```typescript
|
||||
const warp = WarpFactory.forMainnet();
|
||||
```
|
||||
|
||||
If you want to use `Arweave` gateway instead of default `Warp` gateway, go with a custom configuration:
|
||||
|
||||
```typescript
|
||||
const warp = WarpFactory.custom(
|
||||
arweave,
|
||||
{
|
||||
...defaultCacheOptions
|
||||
},
|
||||
'mainnet'
|
||||
)
|
||||
.useArweaveGateway()
|
||||
.build();
|
||||
```
|
||||
|
||||
2. RedStone public testnet
|
||||
|
||||
Previously, you would intialize Warp in testnet environment exactly like you would initialize Warp in mainnet, you would just need to set correct Arweave instance. Now the process is simplified:
|
||||
|
||||
```typescript
|
||||
warp = WarpFactory.forTestnet();
|
||||
```
|
||||
|
||||
3. ArLocal
|
||||
|
||||
This is how you would intialize it previously:
|
||||
|
||||
```typescript
|
||||
warp = WarpNodeFactory.forTesting(arweave);
|
||||
```
|
||||
|
||||
Now:
|
||||
|
||||
```typescript
|
||||
warp = WarpFactory.forLocal();
|
||||
```
|
||||
|
||||
Remember that you are always allowed to initialize Warp depending on your needs by using `custom` factory method.
|
||||
|
||||
#### sqlite to levelDB
|
||||
|
||||
If you've been using Knex based cache you can now easily migrate your sqlite database to levelDB. Just use our [migration tool](./tools/migrate.ts), set correct path to your sqlite database in this line:
|
||||
|
||||
```typescript
|
||||
const result = await warp.migrationTool.migrateSqlite('./tools/sqlite/contracts-3008.sqlite');
|
||||
```
|
||||
|
||||
...and run the script:
|
||||
|
||||
```powershell
|
||||
yarn ts-node -r tsconfig-paths/register tools/migrate.ts
|
||||
```
|
||||
|
||||
### Examples
|
||||
@@ -473,7 +662,19 @@ We've also created an [academy](https://redstone.academy/) that introduces to th
|
||||
|
||||
A community package - [arweave-jest-fuzzing](https://github.com/Hansa-Network/arweave-jest-fuzzing/blob/master/README.md) has been released thanks to Hansa Network to help SmartWeave developers write fuzzy tests.
|
||||
|
||||
### Migration Guide
|
||||
## Warp transaction lifecycle
|
||||
|
||||
If you're already using Arweave smartweave.js SDK and would like to smoothly migrate to Warp SDK -
|
||||
check out the [migration guide](https://github.com/redstone-finance/warp/blob/main/docs/MIGRATION_GUIDE.md).
|
||||

|
||||
|
||||
Warp SDK is just part of the whole Warp smart contracts platform. It makes transactions processing and evaluation easy and effective.
|
||||
|
||||
1. Our Sequencer assigns order to SmartWeave interactions, taking into account sequencer’s timestamp, current Arweave network block height and is salted with sequencer’s key.
|
||||
|
||||
2. Interactions are then packed by Bundlr which guarantees transactions finality and data upload reliability.
|
||||
The ability to directly process rich content
|
||||
|
||||
3. Transactions are stored on Arweave where they are available for querying.
|
||||
|
||||
4. The key component for the lazy-evaluation nature of SmartWeave protocol is fast and reliable interaction loading. Thanks to our gateway we guarantee loading transactions in seconds in a reliable way - it has built-in protection against forks and corrupted transactions. Our gateway enables fast queries and efficient filtering of interactions, which in effect greatly reduces state evaluation time.
|
||||
|
||||
5. Lastly, transactions can be evaluated either by our SDK or the evaluation can be delegated to a distribution execution network - a dedicated network of nodes (DEN). Multi-node executors network listens to incoming transactions and automatically update contract state.
|
||||
|
||||
Reference in New Issue
Block a user