Skip to main content

Utility

Utility tools for interacting with the ZDK#

The utility functions are split into 3 categories:

Type Constructors#


The ZORA protocol utilizes a number of structs to encode data as parameters. The ZDK provides some type constructors that can perform some basic validation and return a properly formatted struct.

constructMediaData#

  • Accepts the arguments for constructing MediaData type.
  • Validates that the URIs begins with https://.
  • Validates that the hashes are exactly 32 bytes in length.
NameTypeDescription
tokenURIstringThe uri where the media's content can be accessed
metadataURIstringThe uri where the media's metadata can be accessed
contentHashBytesLikeThe sha256 hash of the media's content
metadataHashBytesLikeThe sha256 hash of the media's metadata
const contentHash = await sha256FromBuffer(Buffer.from('some content'))const metadataHash = await sha256FromBuffer(Buffer.from('some metadata'))
const mediaData = constructMediaData(  'https://token.com',  'https://metadata.com',  contentHash,  metadataHash)

constructAsk#

  • Parses and Validates the currency address to ensure it's a valid Ethereum Address.
NameTypeDescription
currencystringThe currency address of the Ask
amountBigNumberishThe amount of the Ask in the currency's atomic units
const dai = '0x6B175474E89094C44Da98b954EedeAC495271d0F'const decimal100 = Decimal.new(100)const ask = constructAsk(dai, decimal100.value)

constructBid#

  • Parses and Validates the bidder, recipient, and currency addresses.
  • Rounds the SellOnShare to 4 decimals of precision.
NameTypeDescription
currencystringThe currency address of the Bid
amountBigNumberishThe amount of the Bid in the currency's atomic units
bidderstringThe address of the Bid's bidder
recipientstringThe address of the Bid's recipient
sellOnSharenumberThe sellOnShare of the Bid
const dai = '0x6B175474E89094C44Da98b954EedeAC495271d0F'const decimal100 = Decimal.new(100)const bidder = '0xf13090cC20613BF9b5F0b3E6E83CCAdB5Cd0FbD5'const bid = constructBid(dai, decimal100.value, bidder, bidder, 33.3333)

constructBidShares#

  • Accepts number args, converts them to ethers BigNumber type with 18 decimals of precision.
  • Performs validation that the BigNumber representations sum to 100 in BigNumber form.
NameTypeDescription
creatornumberThe creator bidshare for the media
ownernumberThe owner bidshare for the media
prevOwnernumberThe prevOwner bidshare for the media
const bidShares = constructBidShares(10, 90, 0)

Hashing Utilities#


All NFTs minted on the ZORA Protocol store a sha256 hash of both its content and metadata. This tool makes it easy for developers to both create and verify hashes.

The majority of NFT protocols don't currently support storing integrity tools like a sha256 checksum. This means that if the metadata URL were to ever change, the NFT would become corrupted with no way to verify the originality of the data.

By providing an on-chain integrity check, anyone is able to ensure that a ZORA NFT has not been corrupted in any way.

sha256FromBuffer#

Create a sha256 from a Buffer object

NameTypeDescription
bufferBufferThe Buffer to be hashed
const buf = await fs.readFile('path/to/file')const hash = sha256FromBuffer(buf)
const otherBuffer = Buffer.from('someContent')const otherHash = sha256FromBuffer(otherBuffer)

sha256FromHexString#

Create a sha256 hash from a hex string. Hex string must be prefixed with 0x

NameTypeDescription
datastringThe hex encoded data to be hashed
const buf = Buffer.from('someContent')const hexString = '0x'.concat(buf.toString('hex'))const hash = sha256FromHexString(hexString)

sha256FromFile#

Create a sha256 hash from a local file. This is most useful for the hashing of large files. It uses a readStream to load bits into memory via a buffer and construct a hash as it consumes the contents of the file.

NameTypeDescription
pathToFilestringThe path to the file to be hashed
chunkSizenumberThe chunk size in bytes for the read stream to read into memory
const hash = await sha256FromFile('path/to/file', 16 * 1024)

EIP-712 Utilities#


EIP-712 is a standard for hashing and signing of data.

signPermitMessage#

Permit was specified as an extension of ERC-20 standard to allow for users to issue approval to accounts without needing ETH.

We have extended it further to be used for the ZORA Protocol, so that users can delegate approvals to other smart contracts to perform actions that approved users can do such as:

  • setAsk
  • acceptBid
  • updateContentURI
  • updateMetadataURI
  • transfer

The signer must be an ethers Wallet object.

NameTypeDescription
ownerWalletThe owners's wallet
toAddressstringThe address being granted the permit
mediaIdnumberThe ID of the media
noncenumberThe permitNonce of the owner address
deadlinenumberThe deadline of the signature to be included in a tx
domainEIP712DomainThe EIP712Domain for the permit sig
const provider = new JsonRpcProvider()const [mainWallet, otherWallet] = generatedWallets(provider)const rinkebyZora = new Zora(mainWallet, 4)const deadline = Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 // 24 hoursconst domain = rinkebyZora.eip712Domain()const eipSig = await signPermitMessage(  mainWallet,  otherWallet.address,  0, // mediaId  0, // nonce  deadline,  domain)

signMintWithSigMessage#

We extended EIP-712 to allow for creators to mint without needing ETH. A user can sign a mintWithSig message and use a trusted relayer to relay the transaction and mint on their behalf.

NameTypeDescription
ownerWalletThe owners's wallet
contentHashBytesLikeThe sha256 hash of the media's content
metadataHashBytesLikeThe sha256 hash of the media's metadata
creatorShareBNBigNumberThe creator share of the media
noncenumberThe mintWithSigNonce of the owner address
deadlinenumberThe deadline of the signature to be included in a tx
domainEIP712DomainThe EIP712Domain for the mintWithSig signature
const provider = new JsonRpcProvider()const [mainWallet, otherWallet] = generatedWallets(provider)const rinkebyZora = new Zora(otherWallet, 4)
const contentHash = await sha256FromBuffer(Buffer.from('some content'))const metadataHash = await sha256FromBuffer(Buffer.from('some metadata'))const contentURI = 'https://token.com'const metadataURI = 'https://metadata.com'
const mediaData = constructMediaData(contentURI, metadataURI, contentHash, metadataHash)const bidShares = constructBidShares(10, 90, 0)const deadline = Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 // 24 hoursconst domain = rinkebyZora.eip712Domain()const nonce = await rinkebyZora.fetchMintWithSigNonce(mainWallet.address)const eipSig = await signMintWithSigMessage(  mainWallet,  contentHash,  metadataHash,  Decimal.new(10).value,  nonce.toNumber(),  deadline,  domain)

recoverSignatureFromPermit#

Recover the address of the signing private key of a Permit message.

NameTypeDescription
ownerWalletThe owners's wallet
toAddressstringThe address being granted the permit
mediaIdnumberThe ID of the media
noncenumberThe permitNonce of the owner address
deadlinenumberThe deadline of the signature to be included in a tx
domainEIP712DomainThe EIP712Domain for the permit sig
sigEIP712SignatureThe EIP712Signature to have an address recovered
const provider = new JsonRpcProvider()const [mainWallet, otherWallet] = generatedWallets(provider)const zora = new Zora(provider, 4)const deadline = Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 // 24 hoursconst domain = zora.eip712Domain()const eipSig = await signPermitMessage(  mainWallet,  otherWallet.address,  1,  1,  deadline,  domain)
const recovered = await recoverSignatureFromPermit(  otherWallet.address,  1,  1,  deadline,  domain,  eipSig)
if (recovered.toLowerCase() != mainWallet.address.toLowerCase()) {  console.log('Unable to Validate Signature')} else {  console.log('Signature Validated')}

recoverSignatureFromMintWithSig#

Recover the address of the signing private key of a mintWithSig message

NameTypeDescription
ownerWalletThe owners's wallet
contentHashBytesLikeThe sha256 hash of the media's content
metadataHashBytesLikeThe sha256 hash of the media's metadata
creatorShareBNBigNumberThe creator share of the media
noncenumberThe mintWithSigNonce of the owner address
deadlinenumberThe deadline of the signature to be included in a tx
domainEIP712DomainThe EIP712Domain for the mintWithSig signature
sigEIP712SignatureThe EIP712Signature to have an address recovered
const provider = new JsonRpcProvider()const [mainWallet] = generatedWallets(provider)const rinkebyZora = new Zora(provider, 4)const deadline = Math.floor(new Date().getTime() / 1000) + 60 * 60 * 24 // 24 hoursconst domain = rinkebyZora.eip712Domain()
const contentHash = await sha256FromBuffer(Buffer.from('some content'))const metadataHash = await sha256FromBuffer(Buffer.from('some metadata'))
const eipSig = await signMintWithSigMessage(  mainWallet,  contentHash,  metadataHash,  Decimal.new(10).value,  1,  deadline,  domain)
const recovered = await recoverSignatureFromMintWithSig(  contentHash,  metadataHash,  Decimal.new(10).value,  2,  deadline,  domain,  eipSig)
if (recovered.toLowerCase() != mainWallet.address.toLowerCase()) {  console.log('Unable to Validate Signature')} else {  console.log('Signature Validated')}