Skip to main content

Warp Contracts Plugin - Deploy Plugin

Warp Contracts SDK's main aim is to serve as a contract evaluator. However, it can be extended with DeployPlugin which enables several contract deployment methods.

Installation and usage

In order to use DeployPlugin firstly, install warp-contracts-plugin-deploy:

yarn add warp-contracts-plugin-deploy

npm install warp-contracts-plugin-deploy

...and then attach it to the Warp instance:

import { DeployPlugin } from 'warp-contracts-plugin-deploy';
import { WarpFactory } from 'warp-contracts';

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

Now, all the deployment methods are available directly from the Warp instance, e.g.:

const { contractTxId, srcTxId } = await warp.deploy({
wallet: new ArweaveSigner(wallet),
initState: JSON.stringify(initialState),
src: jsContractSrc,
});

Signer

In order to use most of the deployment methods, you will need a wallet which serves as a way of identifying on blockchain. In order to generate one you can simply create using:

Arweave

Ethereum

You will then pass wallet to the deployment methods by setting it as a constructor to one of the dedicated objects. They can all be imported from warp-contracts-plugin-deploy:

SERVER ENVIRONMENT

  • ArweaveSigner
  • EthereumSigner

All you need to do is save wallet's keyfile and include it in your project (preferably in .secrets folder which won't be exposed to the public).

Arweave Signer

const wallet = JSON.parse(fs.readFileSync('<path_to_wallet>', 'utf-8'));
const { contractTxId } = await warp.deploy({
wallet: new ArweaveSigner(wallet),
initState: JSON.stringify(initialState),
src: contractSrc,
});

BROWSER ENVIRONMENT

  • InjectedArweaveSigner
  • InjectedEthereumSigner

InjectedArweaveSigner using arweave.app with arweave-wallet-connector

const wallet = new ArweaveWebWallet({
name: 'Your application name',
logo: 'URL of your logo to be displayed to users',
});

wallet.setUrl('arweave.app');
await wallet.connect();
const userSigner = new InjectedArweaveSigner(wallet);
await userSigner.setPublicKey();
const { contractTxId } = await warp.deploy({
wallet: userSigner,
initState: JSON.stringify(initialState),
src: contractSrc,
});

InjectedArweaveSigner using ArConnect

if (window.arweaveWallet) {
await window.arweaveWallet.connect(['ACCESS_ADDRESS', 'SIGN_TRANSACTION', 'ACCESS_PUBLIC_KEY', 'SIGNATURE']);
}
const userSigner = new InjectedArweaveSigner(window.arweaveWallet);
await userSigner.setPublicKey();
const { contractTxId } = await warp.deploy({
wallet: userSigner,
initState: JSON.stringify(initialState),
src: contractSrc,
});

InjectedEthereumSigner using Metamask and ethers version 5

await window.ethereum.request({ method: 'eth_requestAccounts' });
const provider = new ethers.providers.Web3Provider(window.ethereum);
const userSigner = new InjectedEthereumSigner(provider);
await userSigner.setPublicKey();
const { contractTxId } = await warp.deploy({
wallet: userSigner,
initState: JSON.stringify(initialState),
src: contractSrc,
});

InjectedEthereumSigner using Metamask and ethers version 6

await window.ethereum.request({ method: 'eth_requestAccounts' });
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
provider.getSigner = () => signer;
const userSigner = new InjectedEthereumSigner(wallet);
await userSigner.setPublicKey();
const { contractTxId } = await warp.deploy({
wallet: userSigner,
initState: JSON.stringify(initialState),
src: contractSrc,
});

Initial state

Each contract should have initial state which can be then changed by calling contract interaction functions. It's represented as a simple object, e.g.:

{
"owner": "uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M",
"canEvolve": true,
"balances": {
"uhE-QeYS8i4pmUtnxQyHD7dzXFNaJ9oMK-IM-QPNY6M": 10000000
}
}

When passing initial state as an argument to the deployment method, it should be stringified.

Contract Source

Contract source is the essence of the contract containing all interaction functions. It has to be written in Javascript (or compiled to either Javascript or WASM) and then passed to the deployment method. You can learn a lot more about how to write contract source in one of the tutorials - Ardit or PST.

Deployment methods

deploy

Deploys contract to Arweave. Two separate transactions are deployed - one with contract's source and another - with contracts' metadata and its initial state.
Such separation allows to deploy multiple contracts using the exact same source transaction.

By default, deployment transactions are bundled and posted to Arweave using Warp Gateway.
If you want to deploy your contract directly to Arweave - disable bundling by setting disableBundling to true.

The ContractDeploy result contains

  • contractTxId - the id of the newly deployed contract
  • srcTxId - the id the transaction that contains the contract's source code
async function deploy(contractData: ContractData, disableBundling?: boolean): Promise<ContractDeploy>;
Example
const initialState = {};
const wallet = JSON.parse(fs.readFileSync('<path_to_wallet>', 'utf-8'));
const contractSrc = fs.readFileSync(path.join('<path_to_your_contract.js>'), 'utf8');

const { contractTxId, srcTxId } = await warp.deploy({
wallet: new ArweaveSigner(wallet), // usually your Arweave wallet
initState: JSON.stringify(initialState), // remember to stringify the initial state object
src: contractSrc,
});

If you want to deploy contract with a WASM contract source, simply pass additional arguments indicating path to the source code and WASM glue code. You can learn more about writing WASM contracts in a dedicated WASM templates repository.

Example
const initialState = {};
const contractSrc = fs.readFileSync(path.join('<path_to_your_contract.wasm>'));

const { contractTxId, srcTxId } = await warp.deploy({
wallet: new ArweaveSigner(wallet), // usually your Arweave wallet
initState: JSON.stringify(initialState), // remember to stringify the initial state object
src: contractSrc,
wasmSrcCodeDir: path.join(__dirname, '<path_to_the_source_code>'),
wasmGlueCode: path.join(__dirname, '<path_to_the_wasm_glue_code.js>'),
});

deployFromSourceTx

Deploys contract from a source transaction. By default, deployment transaction is bundled and posted on Arweave using Warp Gateway. If you want to deploy your contract directly to Arweave - disable bundling by setting disableBundling to true.

async function deployFromSourceTx(
contractData: FromSrcTxContractData,
disableBundling?: boolean
): Promise<ContractDeploy>;
Example
const { contractTxId, srcTxId } = await warp.deployFromSourceTx({
wallet,
initState: initialState,
srcTxId: 'SRC_TX_ID',
});

deployBundled

Uses Warp Gateway's endpoint to upload raw data item to Bundlr and index it.

Example
const { contractTxId } = await warp.deployBundled(rawDataItem);

register

Registering contract is descirbed in details in Register contract section.

createSource

Creating source is described in details in Contracts upgrades section.

saveSource

Saving source is described in details in Contracts upgrades section.

Bundled contract format

You can learn more about how your contract is being posted to Arweave in Bundled contract format section.