Whether it's to deploy a contract from a wasm code or using an existing wasm code hash. You can do it using the ContractDeployer.
Initialize ContractDeployer
import { DedotClient, WsProvider } from'dedot';import { ContractDeployer } from'dedot/contract';import { stringToHex } from'dedot/utils'import { FlipperContractApi } from'./flipper';import flipperMetadata from'./flipper.json'assert { type:'json' };// instanciate an api clientconstclient=awaitDedotClient.new(newWsProvider('...'));// load contract wasm or prepare a wasm codeHashconstwasm='0x...';constexistingCodeHash='0x...'// uploaded wasm// create a ContractDeployer instanceconstdeployer=newContractDeployer<FlipperContractApi>(client, flipperMetadata, wasm);// OR from existingCodeHash// const deployer = new ContractDeployer<FlipperContractApi>(client, flipperMetadata, existingCodeHash);
Dry-run the contract instantiation
Dry run the constructor call to help validate the contract instantiation and estimate gas-fee for the transaction.
constCALLER='5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; // Alice// Some random salt to prevent duplication issue// Salt is optional, you can skip this to use an empty salt constsalt=stringToHex('random-salt'); // Dry run the constructor call for validation and gas estimation// An Error will be thrown out if there's a DispatchError or LangError (contract level error)// More on this in the handling error section belowconstdryRun=awaitdeployer.query.new(true, { caller:CALLER, salt })const { raw: { gasRequired,storageDeposit } } = dryRun;
Error handling if contract constructor returning a Result<Self, Error>
In case the contract constructor returning a Result<Self, Error>, you can also check the see if the instantiation get any errors before submitting the transaction.
const { data,raw } =awaitdeployer.query.new(true, { caller:ALICE, salt })if (data.isErr) {console.log('Contract instantiation returning an error:',data.err);} else {// submitting the transaction}
Submit contract instantiation transaction
After dry-run the transaction to make sure there will be no errors. Now let's submit the transaction to instantiate the contract and listen for events to extract contract address.
// Submitting the transaction to instanciate the contractawaitdeployer.tx.new(true, { gasLimit: gasRequired, salt }).signAndSend(CALLER, ({ status, events}) => {if (status.type ==='BestChainBlockIncluded'||status.type ==='Finalized') {// fully-typed eventconstinstantiatedEvent=client.events.contracts.Instantiated.find(events);constcontractAddress=instantiatedEvent.palletEvent.data.contract.address();console.log(contractAddress); } });
Listen for contract.Instantiated event from system events