Solana[part21]_ETF的赎回

Solana[part21]_ETF的赎回

代码:https://github.com/SoniaChan33/iswap/commit/c648cb122b2cc9a80a8085d78bdc9033ab83c954

赎回 ETF

以 ETF No.1 为例,ETF No.1 包含 jitoSOL 和 mSOL,权重为 20%、80%

当前价格: 1 JitoSOL = 1.06 SOL 1 mSOL = 1.35 SOL

用户当前持有 100 份 ETF No.1,计划卖出 ETF No.1 100 份

获得:(100 \times 20% \times 1.06 + 100 \times 80% \times 1.35 = 129.2 \ \text{SOL})

方案:

  1. 【用户】【Burn】100 份 ETF No.1(注:原文 “ETE” 为笔误,应为 “ETF”)
  2. 【合约】【Transfer】JitoSOL 20 份和 mSOL 80 份到【用户】
  3. 【用户】通过 ray 或者 okx 等平台,将 80 mSOL 和 20 JitoSOL 兑换为 129.2 SOL
➜  anchor git:(main) ✗ spl-token accounts                        
Token                                         Balance
-----------------------------------------------------
6RQFEKBGuqJAasPDLZEK2Uk3pLMEEo3xfSgz5AvjU65H  200
76EV8QxLELcs63zrjwu9o1ifeX9LaYMixrzwmSHp7EHH  10 
HhGykz9QW6hTZ4kcfcfGPDVxmRQ2hGAFtAehBrwxdDNE  90 

成功赎回


➜  anchor git:(main) ✗ spl-token accounts           
Token                                         Balance
-----------------------------------------------------
6RQFEKBGuqJAasPDLZEK2Uk3pLMEEo3xfSgz5AvjU65H  100
76EV8QxLELcs63zrjwu9o1ifeX9LaYMixrzwmSHp7EHH  100
HhGykz9QW6hTZ4kcfcfGPDVxmRQ2hGAFtAehBrwxdDNE  100

扩展信息

前置准备:安装一些依赖

➜  anchor git:(main)pnpm install @metaplex-foundation/mpl-token-metadata
➜  anchor git:(main)pnpm install @metaplex-foundation/umi
➜  anchor git:(main)pnpm install @metaplex-foundation/umi-web3js-adapters

导入

import { createUmi } from "@metaplex-foundation/umi-bundle-defaults"
import { fetchDigitalAsset, mplTokenMetadata } from "@metaplex-foundation/mpl-token-metadata";
import { fromWeb3JsPublicKey } from "@metaplex-foundation/umi-web3js-adapters"

获取ETF的一些信息

// 获取etf详情
export async function etfDetail(
    wallet: anchor.Wallet,
    eftAddress: PublicKey,
) {

    // const mintAccount = await getMint(provider.connection, eftAddress);
    // return mintAccount;

    const [etfTokenInfoAddress,] = deriveEtfInfoAccount(eftAddress);
    const etfInfo = await program.account.etfToken.fetch(etfTokenInfoAddress);

    // 创建Umi实例
    const umi = createUmi(provider.connection.rpcEndpoint)
    umi.use(mplTokenMetadata())
    // 获取mint账户信息
    const mintAccount = await fetchDigitalAsset(umi, fromWeb3JsPublicKey(eftAddress));
    let log = ""
    if (mintAccount.metadata.uri) {
        const response = await fetch(mintAccount.metadata.uri);
        const rj = await response.json();
        log = rj.image;
    }
    return {
        public_key: eftAddress.toString(),
        supply: mintAccount.mint.supply,
        decimal: mintAccount.mint.decimals,
        name: mintAccount.metadata.name,
        symbol: mintAccount.metadata.symbol,
        description: etfInfo.descriptor,
        creator: etfInfo.creator.toString(),
        create_at: etfInfo.createAt.toNumber(),
        logo: log
    }
}

// 获取etf的数量
export async function etfAmount(
    wallet: anchor.Wallet,
    eftAddress: PublicKey,
) {

    // 用户钱包ATA
    const ata = getAssociatedTokenAddressSync(
        eftAddress,
        wallet.publicKey
    );

    const mintAccount = await getAccount(provider.connection, ata);
    return mintAccount.amount;
}

输出

➜  anchor git:(main) ✗ anchor run example
{
  address: PublicKey [PublicKey(2cKK6qLFkNGUxaBeLkPDyDkecroPVXYU1gAuadAD9KUx)] {
    _bn: <BN: 17e7b884e0e312137f273e5411cb4e238a7ad46b7efa97e71f6d19e86774a8fd>
  },
  mint: PublicKey [PublicKey(6RQFEKBGuqJAasPDLZEK2Uk3pLMEEo3xfSgz5AvjU65H)] {
    _bn: <BN: 508aa85ad2105c7f71d84700d877d7ae7910d5de69aa3742f381f1da8e3938e4>
  },
  owner: PublicKey [PublicKey(FcKkQZRxD5P6JwGv58vGRAcX3CkjbX8oqFiygz6ohceU)] {
    _bn: <BN: d91024e709f54d65b29c9328658d06a488414c4cabc36522130c330322428769>
  },
  amount: 100000000000n,
  delegate: null,
  delegatedAmount: 0n,
  isInitialized: true,
  isFrozen: false,
  isNative: false,
  rentExemptReserve: null,
  closeAuthority: null,
  tlvData: <Buffer >
}