自定义守卫

为Candy Machine生成自定义Guard客户端

一旦您为Candy Machine Guard程序编写了自定义guard,您需要生成一个与Umi SDK配合使用的Kinobi客户端,例如能够在前端中使用您的guard。

生成IDL和初始客户端

配置Shankjs

Shankjs是一个IDL生成器,适用于Anchor和非Anchor程序。您需要使用新的自定义Candy Guard部署密钥进行配置,以正确生成可用的客户端。编辑位于mpl-candy-machine仓库中的/configs/shank.cjs文件。

/configs/shank.cjs
generateIdl({
generator: "anchor",
programName: "candy_guard",
programId: "Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g", // 您的自定义Candy Guard部署的程序密钥。
idlDir,
binaryInstallDir,
programDir: path.join(programDir, "candy-guard", "program"),
});

如果您使用anchor 28生成,由于缺少crates.io crate,您需要在Shankjs IDL生成器中添加一个回退到anchor 27。

/configs/shank.cjs
generateIdl({
generator: "anchor",
programName: "candy_guard",
programId: "Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g", // 您的自定义Candy Guard部署的程序密钥。
idlDir,
binaryInstallDir,
programDir: path.join(programDir, "candy-guard", "program"),
rustbin: {
locked: true,
versionRangeFallback: "0.27.0",
},
});

生成IDL和客户端

现在您应该能够生成IDL和初始客户端了。从项目根目录运行

pnpm run generate

这将依次执行pnpm generate:idlspnpm generate:clients两个脚本并构建初始客户端。 如果您出于某种原因需要单独运行这些脚本,您可以这样做。

将Guard添加到客户端

创建Guard文件

一旦成功生成初始客户端,导航到/clients/js/src

第一步是将您的新guard添加到/clients/js/src/defaultGuards文件夹中。

以下是一个模板,您可以根据您创建的guard类型使用并调整以满足您的需求。 您可以随意命名您的guard,但我将我的示例命名为customGuard.ts

import { PublicKey } from '@metaplex-foundation/umi'
import {
getCustomGuardSerializer,
CustomGuard,
CustomGuardArgs,
} from '../generated'
import { GuardManifest, noopParser } from '../guards'
export const customGuardManifest: GuardManifest<
CustomGuardArgs,
CustomGuard,
CustomGuardMintArgs
> = {
name: 'customGuard',
serializer: getCustomGuardSerializer,
mintParser: (context, mintContext, args) => {
const { publicKeyArg1, arg1 } = args
return {
data: new Uint8Array(),
// 从您的铸造参数传入您的自定义guard所需的任何账户。
// 您的guard可能需要也可能不需要剩余账户。
remainingAccounts: [
{ publicKey: publicKeyArg1, isWritable: true },
{ publicKey: publicKeyArg2, isWritable: false },
],
}
},
routeParser: noopParser,
}
// 在这里您需要填写您的guard操作所需的任何自定义铸造参数。
// 您的guard可能需要也可能不需要MintArgs。
export type CustomGuardMintArgs = {
/**
* 自定义Guard铸造参数1
*/
publicKeyArg1: PublicKey
/**
* 自定义Guard铸造参数2
*/
publicKeyArg2: PublicKey
/**
* 自定义Guard铸造参数3。
*/
arg3: Number
}

将Guard添加到现有文件

从这里您需要将您的新guard添加到一些现有文件中。

/clients/js/src/defaultGuards/index.ts导出您的新guard

...
export * from './tokenGate';
export * from './tokenPayment';
export * from './token2022Payment';
// 将您的guard添加到列表中
export * from './customGuard';

/clients/js/src/defaultGuards/defaults.ts中将您的guard添加到这些位置;

import { CustomGuardArgs } from "../generated"
export type DefaultGuardSetArgs = GuardSetArgs & {
...
// 将您的guard添加到列表中
customGuard: OptionOrNullable<CustomGuardArgs>;
}
import { CustomGuard } from "../generated"
export type DefaultGuardSet = GuardSet & {
...
// 将您的guard添加到列表中
customGuard: Option<CustomGuard>
}
import { CustomGuardMintArgs } from "./defaultGuards/customGuard.ts"
export type DefaultGuardSetMintArgs = GuardSetMintArgs & {
...
// 将您的guard添加到列表中
customGuard: OptionOrNullable<CustomGuardMintArgs>
}
export const defaultCandyGuardNames: string[] = [
...// 将您的guard添加到列表中
'customGuard',
]

最后,您需要将导出的customGuardManifest添加到位于/clients/js/src/plugin.ts的插件文件中

import {customGuardManifest} from "./defaultGuards"
umi.guards.add(
...// 将您的guard manifest添加到列表中
customGuardManifest
)

从这一点开始,您可以构建并将您的客户端包上传到npm,或将其链接/移动到您想要访问新guard客户端的项目文件夹中。

值得使用内置的AVA测试套件编写一些测试,在多种场景中充分测试您的guard。测试示例可以在/clients/js/tests中找到。