> ## Documentation Index
> Fetch the complete documentation index at: https://docs.story.foundation/llms.txt
> Use this file to discover all available pages before exploring further.

# Encode Function Data

> A short tutorial on how to encode Story smart contract function data for things like Crossmint.

Sometimes you want to encode smart contract function data for things like [sending arbitrary transactions via Crossmint](https://docs.crossmint.com/solutions/story-protocol/wallets/server-side-wallets#send-arbitrary-transaction).

As seen [in Crossmint's docs](https://docs.crossmint.com/solutions/story-protocol/wallets/server-side-wallets#send-arbitrary-transaction), 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.

<CardGroup cols={1}>
  <Card title="Completed Code" href="https://github.com/storyprotocol/typescript-tutorial/blob/main/scripts/misc/sendRawTransaction.ts" icon="code">
    View the completed code for this tutorial.
  </Card>
</CardGroup>

## Step 1: Get the function data

As an example, let's try to call the [mintAndRegisterIpAndAttachPilTerms](https://github.com/storyprotocol/protocol-periphery-v1/blob/main/contracts/workflows/LicenseAttachmentWorkflows.sol#L130) in our periphery contract. This function mints & registers a new IP and attaches [PIL Terms](/concepts/programmable-ip-license/pil-terms) to it.

As shown in [Deployed Smart Contracts](/developers/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](https://aeneid.storyscan.io/address/0xcC2E862bCee5B6036Db0de6E06Ae87e524a79fd8). 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](https://aeneid.storyscan.io/address/0x887c22833bf7F8E0E19F7d994fec964A82c030FB?tab=contract_abi).

2. Function Args - you can get these just by looking at the [code](https://github.com/storyprotocol/protocol-periphery-v1/blob/main/contracts/workflows/LicenseAttachmentWorkflows.sol#L130).

Great! Now let's build our transaction request.

```typescript theme={null}
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](https://docs.crossmint.com/solutions/story-protocol/wallets/server-side-wallets#send-arbitrary-transaction).

However we could also then send this transaction ourselves:

```typescript theme={null}
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!

<CardGroup cols={2}>
  <Card title="Completed Code" href="https://github.com/storyprotocol/typescript-tutorial/blob/main/scripts/misc/sendRawTransaction.ts" icon="code">
    View the completed code for this tutorial.
  </Card>

  <Card title="Learn More" href="/developers/tutorials" icon="book-open">
    Explore more tutorials in our documentation
  </Card>
</CardGroup>
