Skip to content

Stack.so middleware

Connect to Stack.so for managing your loyalty program.

cmd
bun add @stackso/js-core

Instructions

  • Set the STACK_API_KEY in the .env file.
  • Create a new point system on Stack.so
  • Add the pointSystemId id to the .env file

Connect to Stack.so

src/lib/stack.ts
import { StackClient } from "@stackso/js-core";
 
let stack: StackClient | null = null;
 
export function getStackClient(): StackClient | null {
  if (!process?.env?.STACK_API_KEY) {
    console.log("No STACK_API_KEY found in .env");
    return null;
  }
  if (!stack) {
    stack = new StackClient({
      apiKey: process.env.STACK_API_KEY as string,
      pointSystemId: 2893,
    });
  }
  return stack;
}
export type { StackClient };

Example handler

src/handler/loyalty.ts
import { XMTPContext, AbstractedMember } from "@xmtp/message-kit";
import { getStackClient } from "../lib/stack.js";
 
export async function handler(context: XMTPContext, fake?: boolean) {
  const stack = getStackClient();
  const {
    members,
    group,
    message: {
      sender,
      typeId,
      content: { skill, params, text },
    },
  } = context;
  if (text) {
    if (skill === "points") {
      const points = await stack?.getPoints(sender.address);
      context.reply(`You have ${points} points`);
      return;
    } else if (skill === "leaderboard") {
      const leaderboard = await stack?.getLeaderboard();
      const formattedLeaderboard = leaderboard?.leaderboard
        .map(
          (entry, index) =>
            `${index + 1}. Address: ${`${entry.address.slice(
              0,
              6,
            )}...${entry.address.slice(-4)}`}, Points: ${entry.points}`,
        )
        .join("\n");
      context.reply(
        `Leaderboard:\n\n${formattedLeaderboard}\n\nCheck out the public leaderboard\nhttps://www.stack.so/leaderboard/degen-group`,
      );
      return;
    }
  } else if (typeId === "group_updated") {
    const { initiatedByInboxId, addedInboxes } = params;
    const adminAddress = members?.find(
      (member: AbstractedMember) => member.inboxId === initiatedByInboxId,
    );
    if (addedInboxes && addedInboxes.length > 0) {
      //if add someone to the group
      await stack?.track("referral", {
        points: 10,
        account: adminAddress?.address ?? "",
      });
    }
  }
}