Skip to content

Releases: warp-contracts/warp

Custom SmartWeave extension plugin

30 Dec 14:59
Compare
Choose a tag to compare

This release enables creating custom SmartWeave extension plugins. It is required for these plugins to implement WarpPlugin interface and set the plugin to a type starting with smartweave-extension-.

Plugin's process method is then called during contract execution and required is set as the property of SmartWeave.extensions object (available globally in the contract).

An example of such plugin implementation:

import { WarpPlugin, WarpPluginType } from 'warp-contracts';
import { custom } from 'custom-library';

class CustomExtension implements WarpPlugin<any, void> {
  process(input: any): void {
    input.custom = custom;
  }

  type(): WarpPluginType {
    return 'smartweave-extension-custom';
  }
}

How to use the plugin during state execution?

const warp = WarpFactory.forMainnet().use(new CustomExtension());

What's Changed

Full Changelog: v1.2.40...v1.2.41

Fetch options plugin

29 Dec 10:13
Compare
Choose a tag to compare

Following release introduces new Warp plugin which allows to update fetch options for the endpoints and therefore allows custom http configuration.

In order to change fetch options one needs to create an implementation of WarpPlugin interface. process method will receive following properties:

interface FetchRequest {
  input: RequestInfo | URL;
  init: Partial<RequestInit>;
}

...and it should return updated fetch options (by returning updated init object). An example of such implementation in src/tools/fetch-options-plugin.ts.

In order to use this plugin, it needs to be attached while creating Warp instance, e.g.:

const warp = WarpFactory.forMainnet().use(new FetchOptionsPlugin());

What's Changed

Full Changelog: v1.2.39...v1.2.40

AtomicNFT - register contract

28 Dec 20:38
Compare
Choose a tag to compare

This released introduces an option to register a contract, that was first deployed via Bundlr.
Used mostly for registering AtomicNFTs - #277.

What's Changed

Full Changelog: 1.2.38...v1.2.39

Contracts' Cache

27 Dec 17:06
Compare
Choose a tag to compare

This release fixes #261.
The contracts cache has been divided into contract metadata cache and contract source cache (since many different contracts share the exact same source with the same source tx id).

What's Changed

Full Changelog: 1.2.37...1.2.38

1.2.37

23 Dec 16:46
Compare
Choose a tag to compare

The release changes the behaviour of the unsafeClient evaluation option.
If it is set to skip - the root contract (if it using the unsafe client) will still throw.

What's Changed

  • fix: root contract with unsafeClient should throw even with unsafeCli… by @ppedziwiatr in #303

Full Changelog: 1.2.36...1.2.37

1.2.36

21 Dec 09:30
Compare
Choose a tag to compare

This releases adds all typed arrays to the types exposed to the VM2.
More details: patriksimek/vm2#484 (comment)

What's Changed

New Contributors

Full Changelog: 1.2.35...1.2.36

unsafeClient evaluation option change, Contract Manifest

13 Dec 12:49
Compare
Choose a tag to compare

Unsafe client evaluation option

Before this release, evaluationOptions.allowUnsafeClient was a boolean value - the SDK either allowed for reading the state of an unsafe contract (i.e. such contract that is using SmartWeave.allowUnsafeClient in its source code; evaluation of such contract is non-deterministic) or threw an exception if allowUnsafeClient was set to false.
This however was an issue in case the contract was interacting with a foreign contract that was using unsafeClient - and at the same time didn't want to allow for unsafeClient to be used. Any interaction with an unsafe contract was causing an exception to be thrown and evaluation to stop.

To mitigate this issue, the allowUnsafeClient has been renamed to unsafeClient and can now accept one of three values:

  1. throw - the default, same as false before this release - will cause the evaluation to stop and throw an exception when a contract with unsafeClient will be detected.
  2. allow - same as true before this release - allows for evaluation of unsafe contract
  3. skip - skips the evaluation of an unsafe contract - a new option, added in this release. It allows to skip evaluation of a foreign contract that is using unsafe client; in such case the validity of the parent contract interaction will be set to false and the error message will contain error like [SkipUnsafeError] Using unsafeClient is not allowed by default.
    NOTE: contract's evolves are also being tracked - e.g. if contract evolves from safe to unsafe - its evaluation will be skipped from that point.
    NOTE: if contract evolves back to safe code (from unsafe code) - it still will be skipped. The reason is that we're unable to determine the state of the contract when it returns to the safe version.

Contract manifest

This release adds a new feature - a contract manifest. Contract manifest is a set of evaluation options that are required by the contract to properly execute.
In order to deploy a contract with a manifest, pass the manifest options in the contractData parameter of the warp.deploy method, e.g.:

const {contractTxId, srcTxId} = await warp.deploy({
      wallet,
      initState: initialState,
      src: jsContractSrc,
      evaluationManifest: {
        evaluationOptions: {
          unsafeClient: 'skip',
          internalWrites: true
        }
      }
    });

In such case - the contract deployment transaction will contain a new tag - Contract-Manifest.
Example - oG4vBpf7IqmadALEM9XmguLTfRlztxDcX8lWdUfiHIM.

If the client's evaluation options are not compatible with the contract's manifest options - an error will be thrown, e.g.:

Error: Option {unsafeClient} differs. EvaluationOptions: [throw], manifest: [skip]. Use contract.setEvaluationOptions({unsafeClient: skip) to evaluate contract state.
Option {internalWrites} differs. EvaluationOptions: [false], manifest: [true]. Use contract.setEvaluationOptions({internalWrites: true) to evaluate contract state.

Interactions between contracts with different manifests

In case of an interaction between two contracts that both define a manifest - the idea is that evaluation of the foreign contract should not be processed with "less secure" evaluation options than those set for the main/root contract (i.e. the one that is being read by the User).

Currently, one exception to this rule are the internal writes.
Consider the examples below:

Example 1:

  1. The root contract blocks internal writes
  2. The foreign contract allows for internal writes
    => the internal writes should be allowed during evaluation of the foreign contract

Example 2:

  1. The root contract has the 'unsafeClient' set to 'skip'
  2. The foreign contract has the 'unsafeClient' to 'allow'
    => the 'unsafeClient' should be set to 'skip' for foreign contract

Example 3:

  1. The root contract has the 'vm2' set to 'true'
  2. The foreign contract has the 'vm2' set to 'false'
    => the 'vm2' for the foreign contract should be set to 'true'

Example 4:

  1. The root contract has the 'maxCallDepth' set to 3
  2. The foreign contract has the 'maxCallDepth' set to 5
    => the 'maxCallDepth' for the foreign contract should be set to '3'
    NOTE: call depth is always verified from the perspective of the root contract!

Example 5:

  1. The root contract has the 'maxInteractionEvaluationTimeSeconds' set to 10
  2. The foreign contract has the 'maxInteractionEvaluationTimeSeconds' set to 60
    => the 'maxInteractionEvaluationTimeSeconds' for the foreign contract should be set to '10'

On the other hand - if the root contract has less secure options than the foreign contract -
the more secure options of the foreign contract should be respected.
Example:

  1. Contract "A" with 'unsafeClient' = 'allow' (and unsafeClient used in its source) is performing
    write operation on Contract "B" that has 'unsafeClient' set to 'skip'.
    i.e. Contract A calls SmartWeave.contracts.write on Contract B.

In this case the more secure setting of the Contract B should be reflected - and write itself
should be blocked (i.e. it should not be even created during the A.writeInteraction - when a dry-run
is being performed, and we're evaluating a list of internal writes for a newly created interaction).

All rules are defined in https://github.com/warp-contracts/warp/blob/main/src/contract/EvaluationOptionsEvaluator.ts#L21

What's Changed

Full Changelog: v1.2.33...1.2.35

Save contract source through Bundlr

02 Dec 15:54
Compare
Choose a tag to compare

This release adds an option to save contract source through Bundlr using Warp Gateway and introduces some significant API changes.

  1. Saving source through Bundlr
    This release splits contract source saving process to two parts - creating source and saving source.
  • createSourceTx - creates and signs contract source transaction, returns signed contract source transaction
createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction>;

usage:

const srcTx = await warp.createSourceTx({ src: contractSrc }, wallet);
  • saveSourceTx - saves source transaction created using createSourceTx method; by default source transaction is sent to Warp Gateway where it is uploaded to Bundlr, if in local environment or bundle is disabled using disableBundling method - source transaction is sent directly to Arweave, returns source transaction id
saveSourceTx(sourceTx: Transaction, disableBundling?: boolean): Promise<string>;

usage:

const srcTxId = await warp.saveSourceTx(srcTx);

Above methods are useful particularly when one contract needs to evolve its current contract source:

const srcTx = await warp.createSourceTx({ src: newJsContractSrc }, wallet);
const newSrcTxId = await warp.saveSourceTx(srcTx);
await contract.evolve(newSrcTxId);

...it is also useful when one contract source should be later used by multiple contracts.

  1. API changes
  • createContract field in Warp instance is now deprecated and will be changed into private field soon. All CreateContract methods are now accessible directly from Warp instance, they can be used like so:
const { contractTxId } = await warp.deploy({
  wallet,
  initState: JSON.stringify(initialState),
  src: contractSrc
});

List of CreateContract methods now available from Warp instance:

async deploy(contractData: ContractData, disableBundling?: boolean): Promise<ContractDeploy>;
async deployFromSourceTx(contractData: FromSrcTxContractData, disableBundling?: boolean): Promise<ContractDeploy>;
async deployBundled(rawDataItem: Buffer): Promise<ContractDeploy>;
async createSourceTx(sourceData: SourceData, wallet: ArWallet | SignatureType): Promise<Transaction> 
async saveSourceTx(srcTx: Transaction, disableBundling?: boolean): Promise<string>

What's Changed

Full Changelog: 1.2.31...v1.2.32

Cache enhancements

01 Dec 10:18
Compare
Choose a tag to compare

This release adds new methods to the SortKeyCache interface:

  1. prune - allows to remove old cache entries - https://github.com/warp-contracts/warp/blob/main/src/cache/SortKeyCache.ts#L65
  2. delete - allows to remove all cached values for a given contract - https://github.com/warp-contracts/warp/blob/main/src/cache/SortKeyCache.ts#L35

What's Changed

New Contributors

Full Changelog: v1.2.30...1.2.31

'Buffer' defined for the contract function executed in browser environment

30 Nov 13:53
Compare
Choose a tag to compare
  • adds Buffer, atob, btoa to the browser version of contract function so it can be defined inside the contract when state is evaluated in the browser
  • removes polyfills from the web bundle (introduced in v1.2.29)
  • upgrades arweave-js version to 1.11.8 (which fixes issues with tx signature verification)
  • changes smartweave-nlp-extension plugin's name to smartweave-nlp-extension and smartweave-ethers-extension to smartweave-extension-ethers

What's Changed

Full Changelog: v1.2.29...v1.2.30