Sometimes you want to encode smart contract function data for things like sending arbitrary transactions via Crossmint.

As seen in Crossmint’s docs, you can get encoded function data via Story’s SDK. However this is shortly going to be deprecated and it does not support every function anyway.

So here’s a quick tutorial on how to get encoded function data for any Story smart contract function.

Step 1: Get the function data

As an example, let’s try to call the mintAndRegisterIpAndAttachPilTerms in our periphery contract. This function mints & registers a new IP and attaches PIL Terms to it.

As shown in Deployed Smart Contracts, LicenseAttachmentWorkflows is deployed at 0xcC2E862bCee5B6036Db0de6E06Ae87e524a79fd8 on Aeneid (at the time of writing this tutorial).

There’s a few things we’ll need:

  1. Contract ABI - you can get this by going to our block explorer and looking up the contract. This is a proxy contract, so go to Contract > Read/Write proxy > Click on the implementation address > Contract > ABI. After all that, you should end up here.

  2. Function Args - you can get these just by looking at the code.

Great! Now let’s build our transaction request.

import { encodeFunctionData } from "viem";
import { Account, Address, privateKeyToAccount } from "viem/accounts";

const account: Account = privateKeyToAccount(
  `0x${process.env.WALLET_PRIVATE_KEY}` as Address
);

const transactionRequest = {
  to: "0xcC2E862bCee5B6036Db0de6E06Ae87e524a79fd8" as `0x${string}`,
  data: encodeFunctionData({
    abi: CONTRACT_ABI, // the abi you copied above
    functionName: "mintAndRegisterIpAndAttachPILTerms",
    args: [
      "0xc32A8a0FF3beDDDa58393d022aF433e78739FAbc", // example spg nft contract I use on Aeneid
      account.address,
      // example metadata values
      {
        ipMetadataURI:
          "https://ipfs.io/ipfs/bafkreiabrkevameeffdpjpizchywldogzai7kp5oodawbhgbojyeomk7uq",
        ipMetadataHash:
          "0x018a895030842946f4bd1911f1658dc6c811f53fae70c1609cc1727047315fa4",
        nftMetadataURI:
          "https://ipfs.io/ipfs/bafkreicbuti233kvewqs7uwb5y2toexj5gafgvsr5mqmnnx7cuof53gvsa",
        nftMetadataHash:
          "0x41a4d1aded5525a12fd2c1ee353712e9e980535651eb20c6b6ff151c5eecd590",
      },
      // example PIL terms
      [
        {
          terms: {
            transferable: true,
            royaltyPolicy: "0xBe54FB168b3c982b7AaE60dB6CF75Bd8447b390E",
            defaultMintingFee: 0n,
            expiration: 0n,
            commercialUse: true,
            commercialAttribution: true,
            commercializerChecker: "0x0000000000000000000000000000000000000000",
            commercializerCheckerData: "0x",
            commercialRevShare: 0,
            commercialRevCeiling: 0n,
            derivativesAllowed: true,
            derivativesAttribution: true,
            derivativesApproval: false,
            derivativesReciprocal: true,
            derivativeRevCeiling: 0n,
            currency: "0x1514000000000000000000000000000000000000",
            uri: "https://github.com/piplabs/pil-document/blob/ad67bb632a310d2557f8abcccd428e4c9c798db1/off-chain-terms/CommercialRemix.json",
          },
          licensingConfig: {
            mintingFee: 0n,
            isSet: false,
            disabled: false,
            commercialRevShare: 0,
            expectGroupRewardPool: "0x0000000000000000000000000000000000000000",
            expectMinimumGroupRewardShare: 0,
            licensingHook: "0x0000000000000000000000000000000000000000",
            hookData: "0x",
          },
        },
      ],
      true,
    ],
  }),
};

Step 2: Send the transaction

At this point, we have the data and to needed for sending this transaction, for example if we were using Crossmint.

However we could also then send this transaction ourselves:

import { aeneid } from "@story-protocol/core-sdk";
import { createWalletClient, http, WalletClient } from "viem";

// other code here

const walletClient = createWalletClient({
  chain: aeneid,
  transport: http("https://aeneid.storyrpc.io"),
  account,
}) as WalletClient;

const txHash = await walletClient.sendTransaction({
  ...transactionRequest,
  account,
  chain: aeneid,
});

console.log(`Transaction sent: https://aeneid.storyscan.io/tx/${txHash}`);

Done!