Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
DaviRain-Su committed Aug 10, 2023
1 parent 5896b4b commit 81c510a
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ sidebar_class_name: green

既然你已经让程序运行起来了,我们来进入前端代码,为Anchor进行调整。这个设置只需要一分钟,稍等一下,我们会修改一些东西。

首先,让我们从我们的程序中引入我们的IDL。只需将整个文件复制并粘贴到 utils 文件夹中,包括JSON和TypeScript格式。
首先,让我们从我们的程序中引入我们的`IDL`。只需将整个文件复制并粘贴到 `utils` 文件夹中,包括JSON和TypeScript格式。

接下来,创建一个名为 WorkspaceProvider.ts 的新组件文件。为了节省一些时间,我们将从我们构建的电影评论前端中粘贴这段代码,然后将所有的"电影评论"实例更改为"锚定NFT质押"。你会注意到我们正在从常量文件夹中导入 PROGRAM_ID ,进入那里并确保程序ID是我们锚定NFT质押程序的新ID(而不是我们Solana原生程序的ID)。
接下来,创建一个名为 `WorkspaceProvider.ts` 的新组件文件。为了节省一些时间,我们将从我们构建的电影评论前端中粘贴这段代码,然后将所有的"电影评论"实例更改为"Anchor NFT质押"。你会注意到我们正在从常量文件夹中导入 `PROGRAM_ID`s ,进入那里并确保程序`ID`是我们锚定NFT质押程序的新`ID`(而不是我们Solana原生程序的`ID`)。

```typescript
import { createContext, useContext } from "react"
Expand Down Expand Up @@ -70,7 +70,7 @@ const MockWallet = {
export { WorkspaceProvider, useWorkspace }
```

还要从电影评论中复制模拟钱包文件,或者创建一个名为 MockWallet.ts 的新组件,并粘贴这段代码。
还要从电影评论中复制模拟钱包文件,或者创建一个名为 `MockWallet.ts` 的新组件,并粘贴这段代码。

```typescript
import { Keypair } from "@solana/web3.js"
Expand All @@ -84,13 +84,13 @@ const MockWallet = {
export default MockWallet
```

确保安装项目serum, npm install @project-serum/anchor
确保安装项目`serum``npm install @project-serum/anchor`

现在打开 npm run dev ,看看本地主机上是否一切正常...如果是的话,我们继续。
现在打开 `npm run dev` ,看看本地主机上是否一切正常...如果是的话,我们继续。

既然我们已经准备好了进口和额外的组件,让我们仔细检查文件,看看我们可以在使用Anchor时简化事情的地方。

跳转到(/pages/_app.tsx)并添加我们的新WorkspaceProvider,确保它被导入。
跳转到(`/pages/_app.tsx`)并添加我们的新`WorkspaceProvider`,确保它被导入。

```typescript
function MyApp({ Component, pageProps }: AppProps) {
Expand Down Expand Up @@ -120,7 +120,7 @@ import * as anchor from @project-serum/anchor
let workspace = useWorkspace()
```

然后在 checkStakingStatus 里面添加这个额外的检查,连同我们的其他检查一起,确保我们有 !workspace.program 。
然后在 `checkStakingStatus` 里面添加这个额外的检查,连同我们的其他检查一起,确保我们有 `!workspace.program`

```typescript
if (
Expand All @@ -131,7 +131,7 @@ if (
)
```

现在跳转到 /utils/accounts.ts 。您可以删除所有的borsh代码,并将 getStakeAccount 代码替换为此代码。这是使用Anchor工作的美妙之处之一,我们不需要担心序列化和反序列化。
现在跳转到 `/utils/accounts.ts` 。您可以删除所有的`borsh`代码,并将 `getStakeAccount` 代码替换为此代码。这是使用Anchor工作的美妙之处之一,我们不需要担心序列化和反序列化。

```typescript
export async function getStakeAccount(
Expand All @@ -151,18 +151,16 @@ export async function getStakeAccount(

现在已经比以前简单多了,对吧?!?

回到 checkStakingStatus 在 StakeOptionsDisplay ,这里被称为 getStakeAccount ,将第一个参数从 connection 更改为 workspace.program 。
回到 `checkStakingStatus``StakeOptionsDisplay` ,这里被称为 `getStakeAccount` ,将第一个参数从 `connection` 更改为 `workspace.program`

打开你的浏览器,确保本地主机上的一切功能正常。

回到StakeOptionsDisplay,向下滚动到 handleStake 函数。
回到`StakeOptionsDisplay`,向下滚动到 `handleStake` 函数。

再次,首先添加一个检查 !workspace.program 的步骤。我们很快就会想要将其添加到我们的 handleUnstake 和 handleClaim 函数中。
再次,首先添加一个检查 `!workspace.program` 的步骤。我们很快就会想要将其添加到我们的 `handleUnstake``handleClaim` 函数中。

你可以立即从我们之前的工作中删除所有这些代码。



```typescript
const account = await connection.getAccountInfo(stakeAccount)
if (!account) {
Expand Down Expand Up @@ -202,9 +200,9 @@ transaction.add(
)
```

这也意味着我们在instructions.ts文件中创建的一堆代码不再需要了。再次跳转到浏览器上测试一下。
这也意味着我们在`instructions.ts`文件中创建的一堆代码不再需要了。再次跳转到浏览器上测试一下。

假设一切正常运作,让我们来解决 handleUnstake 代码。
假设一切正常运作,让我们来解决 `handleUnstake` 代码。

我们抛弃这段代码,因为现在程序已经处理了这一切。

Expand All @@ -225,7 +223,7 @@ if (!account) {
}
```

然后在 transaction.add 里面去掉 createUnstakeInstruction 并用这个替换:
然后在 `transaction.add` 里面去掉 `createUnstakeInstruction` 并用这个替换:

```typescript
transaction.add(
Expand All @@ -243,9 +241,9 @@ transaction.add(
)
```

你会注意到这些账户与 handleStake 相同,再加上一些用于股份铸币和用户ATA的账户
你会注意到这些账户与 `handleStake` 相同,再加上一些用于股份铸币和用户`ATA`的账户

最后,到 handleClaim ,按照相同的模式进行删除,新的transaction.add应该是这样的
最后,到 `handleClaim` ,按照相同的模式进行删除,新的`transaction.add`应该是这样的

```typescript
transaction.add(
Expand All @@ -260,12 +258,12 @@ transaction.add(
)
```

现在你可以直接删除所有的 instructions.ts 文件。快点!!! :)
现在你可以直接删除所有的 `instructions.ts` 文件。快点!!! :)

随意清理掉未使用的导入以整理你的文件。

还有一件事情我们需要做,在令牌目录中,我们已经创建了奖励令牌,现在需要用新的程序ID重新初始化它。在 bld/index.ts 文件中,当调用 await createBldToken 时,需要替换为新的程序ID。然后重新运行 npm run create-bld-token 脚本。如果我们不这样做,我们的兑换将无法正常工作。
还有一件事情我们需要做,在令牌目录中,我们已经创建了奖励令牌,现在需要用新的程序`ID`重新初始化它。在 `bld/index.ts` 文件中,当调用 `await createBldToken` 时,需要替换为新的程序`ID`。然后重新运行 `npm run create-bld-token` 脚本。如果我们不这样做,我们的兑换将无法正常工作。

这将创建一个新的Mint程序ID,您需要将其添加到您的环境变量中。
这将创建一个新的`Mint`程序`ID`,您需要将其添加到您的环境变量中。

就是这样,我们在前端有一些功能正在运作。下周,我们将使用Anchor进行更多的发货,目前我们只是想展示它有多么容易,并让基本功能开始运行。
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,31 @@ sidebar_class_name: green

# 💸 Redeeming with Anchor

回到 lib.rs 文件,找到Redeem结构体。它与Stake非常相似,所以我们将粘贴该代码并根据需要进行编辑。
回到 `lib.rs` 文件,找到`Redeem`结构体。它与`Stake`非常相似,所以我们将粘贴该代码并根据需要进行编辑。

我们不需要的是nft_mint、nft_edition和program_authority。我们需要更改nft_token_account上的约束条件,使令牌授权变为'user',因为我们没有传入mint
我们不需要的是`nft_mint``nft_edition``program_authority`。我们需要更改`nft_token_account`上的约束条件,使令牌授权变为'`user`',因为我们没有传入`mint`

对于stake_state账户,它不再需要初始化,所以我们只需要种子和bump,并使其可变。我们还可以为其添加一些手动约束。
对于`stake_state`账户,它不再需要初始化,所以我们只需要种子和`bump`,并使其可变。我们还可以为其添加一些手动约束。

```rust
constraint = *user.key == stake_state.user_pubkey,
constraint = nft_token_account.key() == stake_state.token_account
```

让我们再添加几个账户,其中一个是 stake_mint,需要是可变的。这是奖励铸币账户。
让我们再添加几个账户,其中一个是 `stake_mint`,需要是可变的。这是奖励铸币账户。

```rust
#[account(mut)]
pub stake_mint: Account<'info, Mint>,
```

另一个是stake_authority,它将是另一个未经检查的账户,所以让我们添加这个检查。
另一个是`stake_authority`,它将是另一个未经检查的账户,所以让我们添加这个检查。

```rust
#[account(seeds = ["mint".as_bytes().as_ref()], bump)]
```

用户的 user_stake_ata 是一个 TokenAccount,具有以下限制条件。
用户的 `user_stake_ata` 是一个 `TokenAccount`,具有以下限制条件。

```rust
#[account(
Expand All @@ -42,13 +42,13 @@ pub stake_mint: Account<'info, Mint>,
pub user_stake_ata: Account<'info, TokenAccount>,
```

关联的 associated_token_program 是一个 AssociatedToken。
关联的 `associated_token_program` 是一个 `AssociatedToken`

```rust
pub associated_token_program: Program<'info, AssociatedToken>,
```

最后,将metadata_program替换为rent
最后,`metadata_program`替换为`rent`

```rust
pub rent: Sysvar<'info, Rent>,
Expand Down Expand Up @@ -109,7 +109,7 @@ it("Redeems", async () => {
.rpc()
```

...然后运行 anchor test ,如果一切正常并且两个测试通过,我们就进入函数并编写赎回逻辑。
...然后运行 `anchor test` ,如果一切正常并且两个测试通过,我们就进入函数并编写赎回逻辑。

首先,让我们进行一些检查,一个是看它是否已初始化,另一个是确保它已经抵押。我们需要在文件底部为这两个情况添加自定义错误。

Expand Down Expand Up @@ -156,7 +156,7 @@ let redeem_amount = (10 * i64::pow(10, 2) * unix_time) / (24 * 60 * 60);
msg!("Elligible redeem amount: {}", redeem_amount);
```

好的,现在我们将实际铸造奖励。首先,我们需要使用我们的程序创建CpiContext。然后,我们在MintTo对象中传递账户信息,包括铸币对象、接收者和授权机构。最后,我们添加种子和金额。
好的,现在我们将实际铸造奖励。首先,我们需要使用我们的程序创建`CpiContext`。然后,我们在`MintTo`对象中传递账户信息,包括铸币对象、接收者和授权机构。最后,我们添加种子和金额。


```rust
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ sidebar_class_name: green

让我们来完成这个任务并检查已发货的产品。我们将完善我们一直在努力开发的质押计划,但不是添加新功能,而是将其全部替换为Anchor。

让我们通过运行 anchor init anchor-nft-staking 来创建一个新项目,或者选择一个你自己的名字。进入 Anchor.toml 文件,并将种子设置为 true ,集群设置为 devnet 。
让我们通过运行 `anchor init anchor-nft-staking` 来创建一个新项目,或者选择一个你自己的名字。进入 `Anchor.toml` 文件,并将种子设置为 `true` ,集群设置为 `devnet`

然后跳转到 /programs/anchor-nft-staking/Cargo.toml ,添加以下依赖项。
然后跳转到 `/programs/anchor-nft-staking/Cargo.toml` ,添加以下依赖项。

```toml
anchor-lang = { version="0.25.0", features = ["init-if-needed"] }
anchor-spl = "0.25.0"
mpl-token-metadata = { version="1.4.1", features=["no-entrypoint"] }
```

好的,打开 lib.rs 文件,让我们构建基本的脚手架。
好的,打开 `lib.rs` 文件,让我们构建基本的脚手架。

让我们添加以下导入,随着我们的进行,每个导入的必要性将变得清晰明了。

Expand All @@ -43,15 +43,15 @@ use mpl_token_metadata::{
};
```

让我们将默认函数的名称更改为 stake ,并将其相关上下文更改为类型 Stake 。
让我们将默认函数的名称更改为 `stake` ,并将其相关上下文更改为类型 `Stake`

然后添加一个名为 redeem 的函数,其上下文类型为 Redeem 。
然后添加一个名为 `redeem` 的函数,其上下文类型为 `Redeem`

最后,对于 unstake ,使用 Unstake 的上下文类型进行相同操作。
最后,对于 `unstake` ,使用 `Unstake` 的上下文类型进行相同操作。

这些是我们要构建的项目,我们首先要处理的是Stake的结构
这些是我们要构建的项目,我们首先要处理的是`Stake`的结构

我们需要一个PDA来存储UserStakeInfo,并且需要一个StakeState枚举来表示PDA的其中一个字段
我们需要一个`PDA`来存储`UserStakeInfo`,并且需要一个`StakeState`枚举来表示`PDA`的其中一个字段

```rust
#[account]
Expand All @@ -71,9 +71,9 @@ pub enum StakeState {
}
```

我们还可以为StakeState添加一个默认值,将其设置为未抵押。
我们还可以为`StakeState`添加一个默认值,将其设置为未抵押。

我们将使用元数据程序。由于这是相对较新的,锚定程序中没有相应的类型。为了像我们的其他程序(例如系统程序、令牌程序等)一样使用它,我们将为其创建一个结构体,并添加一个名为 id 的实现,返回一个 Pubkey ,它是 MetadataTokenId 。
我们将使用元数据程序。由于这是相对较新的,锚定程序中没有相应的类型。为了像我们的其他程序(例如系统程序、令牌程序等)一样使用它,我们将为其创建一个结构体,并添加一个名为 `id` 的实现,返回一个 `Pubkey` ,它是 `MetadataTokenId`


```rust
Expand All @@ -89,9 +89,9 @@ impl anchor_lang::Id for Metadata {

好的,我们现在可以开始处理质押部分了。下面是结构体需要的总共九个账户。需要注意的几个事项。

你会注意到 nft_edition 是一个 Unchecked 账户,这是因为系统中还没有为这种类型的账户创建。所有未核对的账户都需要有一个备注,以便系统知道你将添加手动安全检查,你会在下面看到 CHECK: Manual validation 。
你会注意到 `nft_edition` 是一个 `Unchecked` 账户,这是因为系统中还没有为这种类型的账户创建。所有未核对的账户都需要有一个备注,以便系统知道你将添加手动安全检查,你会在下面看到 `CHECK: Manual validation`

作为提醒,每个账户上的属性是安全检查,以确保账户是正确类型并能执行特定功能。由于用户需要支付,并且 NFT 代币账户将进行更改,两者都具有 mut 属性。一些账户还需要种子,如下所示。
作为提醒,每个账户上的属性是安全检查,以确保账户是正确类型并能执行特定功能。由于用户需要支付,并且 NFT 代币账户将进行更改,两者都具有 `mut` 属性。一些账户还需要种子,如下所示。

所有其他没有任何属性的账户在Anchor中都有自己必需的安全检查,所以我们不需要添加任何属性。

Expand Down Expand Up @@ -127,9 +127,9 @@ pub struct Stake<'info> {
}
```

在我们继续之前,让我们运行 anchor build,这样我们的第一个构建就可以开始了。记住,这是我们的第一个构建,它将生成我们的程序ID。
在我们继续之前,让我们运行 `anchor build`,这样我们的第一个构建就可以开始了。记住,这是我们的第一个构建,它将生成我们的程序ID。

在运行的同时,在 tests 目录中创建一个名为 utils 的新文件夹。在其中创建一个名为 setupNft.ts 的文件。将下面的代码粘贴进去。
在运行的同时,在 `tests` 目录中创建一个名为 `utils` 的新文件夹。在其中创建一个名为 `setupNft.ts` 的文件。将下面的代码粘贴进去。

```ts
import {
Expand Down Expand Up @@ -194,9 +194,9 @@ export const setupNft = async (program, payer) => {

```

下一次运行 npm install @metaplex-foundation/js
下一次运行 `npm install @metaplex-foundation/js`

然后跳转到 anchor-nft-staking.ts 目录中。这是Anchor创建的默认文件。
然后跳转到 `anchor-nft-staking.ts` 目录中。这是Anchor创建的默认文件。

将提供者的默认行更改为两部分,这样我们以后需要时就可以访问提供者。

Expand All @@ -211,9 +211,9 @@ anchor.setProvider(provider)
const wallet = anchor.workspace.AnchorNftStaking.provider.wallet
```

检查您的构建情况,如果已完成,请运行 anchor deploy ,如果失败,您可能需要向自己空投一些SOL。
检查您的构建情况,如果已完成,请运行 `anchor deploy` ,如果失败,您可能需要向自己空投一些SOL。

构建完成后,运行 anchor keys list 并获取程序ID,然后放入 lib.rs 和 Anchor.toml 文件中。如果构建需要一段时间,您可能需要回到这一步。
构建完成后,运行 `anchor keys list` 并获取程序`ID`,然后放入 `lib.rs``Anchor.toml` 文件中。如果构建需要一段时间,您可能需要回到这一步。

回到测试文件。

Expand All @@ -228,7 +228,7 @@ let mint: anchor.web3.PublicKey
let tokenAddress: anchor.web3.PublicKey
```
现在让我们添加一个 before 函数,在测试运行之前调用。你会注意到";"语法,它将解构返回值并设置所有这些值。
现在让我们添加一个 `before` 函数,在测试运行之前调用。你会注意到"`;`"语法,它将解构返回值并设置所有这些值。
```ts
before(async () => {
Expand All @@ -237,7 +237,7 @@ before(async () => {
})
```

跳转到默认测试,将其更改为 it("Stakes", 。首先,我们只是确保函数被调用。我们还没有构建出实际的股权函数,所以这里没有进行任何逻辑测试。
跳转到默认测试,将其更改为 `it("Stakes"`, 。首先,我们只是确保函数被调用。我们还没有构建出实际的股权函数,所以这里没有进行任何逻辑测试。

```ts
it("Stakes", async () => {
Expand All @@ -255,17 +255,17 @@ it("Stakes", async () => {
})
```

现在,运行 anchor test 。假设它通过了,这意味着我们通过了在Stake结构中创建的账户的验证
现在,运行 `anchor test` 。假设它通过了,这意味着我们通过了在`Stake`结构中创建的账户的验证

回到我们的逻辑,以下是抵押工作所需的逐步操作。我们需要获取时钟的访问权限,确保抵押状态已经初始化,并确保它尚未被抵押。

在stake函数中,让我们首先获取时钟。
`stake`函数中,让我们首先获取时钟。

```rust
let clock = Clock::get().unwrap();
```

接下来,我们创建一个CPI来委托该程序作为冻结或解冻我们的NFT的权限。首先,我们设置CPI,然后确定我们要使用的账户,最后设置权限。
接下来,我们创建一个`CPI`来委托该程序作为冻结或解冻我们的NFT的权限。首先,我们设置`CPI`,然后确定我们要使用的账户,最后设置权限。

```rust
msg!("Approving delegate");
Expand All @@ -281,7 +281,7 @@ let cpi_approve_ctx = CpiContext::new(cpi_approve_program,cpi_approve_accounts);
token::approve(cpi_approve_ctx, 1)?;
```

接下来我们开始冻结代币。首先我们设置权限提升,然后调用invoke_signed函数,并传入所有必要的账户和账户信息数组,最后是种子和提升值。
接下来我们开始冻结代币。首先我们设置权限提升,然后调用`invoke_signed`函数,并传入所有必要的账户和账户信息数组,最后是种子和提升值。

```rust
msg!("Freezing token account");
Expand Down
Loading

0 comments on commit 81c510a

Please sign in to comment.