[Testnet] Open Action | Cross-chain Zora Mint (v2)
Mint Zora NFTs on Base, with Bonsai on Polygon
Overview
This is a technical guide on how to integrate our ZoraLzMintActionV2 open action. More details about the open action can be found here: Cross-chain Zora Mint (v2)
Our ZoraLzMintActionV2 action module is deployed and verified on Polygon
Our contract which receives the messages is ZoraLzCreatorV2 - deployed and verified on Base.
đ§ Currently on testnet (Amoy / Base Sepolia)
đ° Any client that processes our Zora open action is eligible for 2.5% (variable) protocol fee on mints
Initialize with the open action
To initialize a publication with the ZoraLzMintActionV2 module, you must provide the details for a Zora NFT where
To process a publication with the ZoraLzMintActionV2 module, you must
Get the total sale price for the mint
Have the actor approve the $BONSAI token transfer to the module
Encode the data needed to process the act
Send the act transaction
âšī¸ Remember that the open action is to pay for mints in Bonsai on Polygon - even though the Zora NFT is on Base and priced in Base Bonsai.
Prepare the act transaction
// 1. Fetch module metadataimport { testnet, LensClient } from"@lens-protocol/client";import { constants } from"viem";constZORA_LZ_MINT_ACTION_V2="0xA5F19D5953B7777537014653e6219983cE82001c";constBONSAI="0x3d2bD0e15829AA5C362a4144FdF4A1112fa29B5c";constlensClient=newLensClient({ environment: testnet });constdata=awaitlensClient.modules.fetchMetadata({ implementation:ZORA_LZ_MINT_ACTION_V2 });const { metadata } = data;// 2. Get the total sale priceconstpointedProfileId=697; constpointedPubId=3; constquantity=1;constactionModule=getActionModule(ZORA_LZ_MINT_ACTION_V2); // ethers ContractconsttotalSalePrice=awaitactionModule.getTotalSalePrice(pointedProfileId, pointedPubId, qty);// 3. Approve the token transferconsttx=awaitgetTokenContract(BONSAI).approve(ZORA_LZ_MINT_ACTION_V2, totalSalePrice);awaittx.wait();// 4. Encode act dataconstparams= { quantity, clientAddress:constants.AddressZero,// client address to earn protocol fee comment:"minted with $BONSAI"// user-provided comment to surface on Zora UI};constactionModuleData=encodeData(JSON.parse(metadata.processCalldataABI), [params.quantity,params.clientAddress,params.comment]);
Send the act transaction (gasless)
There's a lot of steps involved here, so we'll defer to the Lens docs - but here is the general code.
â ī¸ This function assumes your app domain is whitelisted to use gasless
â ī¸ This function assumes that lensClient is authenticated with a profile
import { WalletClient } from"viem";import { OnchainReferrer, RelaySuccessFragment, LensClient } from"@lens-protocol/client";import { omit } from"lodash/object";// NOTE: this assume the given `actionModule` has `metadata.sponsoredApproved` = true// NOTE: this assumes that the passed in `lensClient` is authenticated (see: https://docs.lens.xyz/docs/login)// NOTE: this assumes the app is whitelisted to use gaslessexportconstactWithSignedTypedata=async ( lensClient:LensClient, walletClient:WalletClient, publicationId:string, actionModule:`0x${string}`, actionModuleData:string, referrers?:OnchainReferrer[] // profile to earn mint referral fees):Promise<any> => {try {// get typed dataconsttypedDataResult=awaitlensClient.publication.actions.createActOnTypedData({ actOn: { unknownOpenAction: { address: actionModule, data: actionModuleData } }, for: publicationId, referrers: referrers || [] });const { id,typedData } =typedDataResult.unwrap();// sign itconst [account] =awaitwalletClient.getAddresses();constsignedTypedData=awaitwalletClient.signTypedData({ account, domain:omit(typedData.domain,"__typename"), types:omit(typedData.types,"__typename"), primaryType:"Act", message:omit(typedData.value,"__typename"), });// broadcast onchain, gaslessconstbroadcastResult=awaitlensClient.transaction.broadcastOnchain({ id, signature: signedTypedData });constbroadcastResultValue=broadcastResult.unwrap();if (broadcastResultValue.__typename ==="RelayError") thrownewError("RelayError");// return the tx hash to link to layerzero scanreturn (broadcastResultValue asRelaySuccessFragment).txHash; } catch (error) {console.log(error); }}
đ° A note on mint referral rewards. The function above shows how to pass in referrers data - which when processed by our open action - will include the referrers[0].profileId profile owner as the recipient for Zora Mint Referral rewards.