We can write a contract, ApePackageCreator, that tacks on an ApePOAP NFT to any user shipment that includes a Bored Ape Yacht Club NFT to another user via the PostOffice contract.
// SPDX-License-Identifier: MITpragmasolidity ^0.8.15;import"@openzeppelin/contracts/token/ERC721/IERC721.sol";import"@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";import"./PostOffice.sol";import"./ApePOAP.sol";interface CapsuleData {enumCapsuleType { SIMPLE, ERC20, ERC721, ERC1155 }structCapsuleContent { CapsuleType capsuleType;address[] tokenAddresses;uint256[] tokenIds;uint256[] amounts;string tokenURI; }}contractApePackageCreatorisERC721Holder { PostOffice private postOffice; ApePOAP private apePOAP; IERC721 private boredApe;// replace these with the actual contract addressesaddressconstant POST_OFFICE_ADDRESS =0x3b61403AdE9240699042D3663814a3679dc15d56;addressconstant APE_POAP_ADDRESS =0xC67F5E3a5B697AE004Edd8F84925189a81c6DC4b;addressconstant BORED_APE_ADDRESS =0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D;constructor() { postOffice =PostOffice(POST_OFFICE_ADDRESS); apePOAP =ApePOAP(APE_POAP_ADDRESS); boredApe =IERC721(BORED_APE_ADDRESS); }functioncreateApePackage(address to_,uint256 tokenId,bytes32 passwordHash_,uint64 unlockTimestamp_ ) externalreturns (uint256) {// Transfer Bored Ape from user to this contract boredApe.safeTransferFrom(msg.sender,address(this), tokenId);// Mint a new Ape POAP apePOAP.mint(address(this));address[] memory _tokenAddresses =newaddress[](2); _tokenAddresses[0] =address(boredApe); _tokenAddresses[1] =address(apePOAP);uint256[] memory _tokenIds =newuint256[](2); _tokenIds[0] = tokenId; _tokenIds[1] = apePOAP.tokenOfOwnerByIndex(address(this), apePOAP.balanceOf(address(this)) -1); CapsuleData.CapsuleContent memory _packageContent = CapsuleData.CapsuleContent({ capsuleType: CapsuleData.CapsuleType.ERC721, tokenAddresses: _tokenAddresses, tokenIds: _tokenIds, amounts:newuint256[](2), tokenURI:"https://apepoap.io/metadata" }); SecurityInfo memory _securityInfo =SecurityInfo({ passwordHash: passwordHash_, unlockTimestamp: unlockTimestamp_, keyAddress:address(0), keyId:0 });// ship package through PostOfficeuint256 packageId = postOffice.shipPackage(_packageContent, _securityInfo, to_);return packageId; }functionpickup(uint256 packageId_,stringcalldata rawPassword_,stringcalldata salt_,bool shouldRedeem_ ) external { postOffice.pickup(packageId_, rawPassword_, salt_, shouldRedeem_); }}
ApePackageCreator accepts the recipient's address, the Bored Ape's token ID, a security hash, and an unlock timestamp. It then transfers the Bored Ape NFT from the sender to itself, mints a new ApePOAP NFT for the sender, and creates a new package in the PostOffice contract containing both NFTs. The new package can then be redeemed by the recipient using the PostOffice's methods.