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 contractsrcTxId
- 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.