Browse Source

Merge pull request #347 from metaplex-foundation/plugins/transfer-delegate-rust

added more rust examples for transfer delegate plugin
Tony Boyle 3 tháng trước cách đây
mục cha
commit
1a442409f0
1 tập tin đã thay đổi với 162 bổ sung4 xóa
  1. 162 4
      src/pages/core/plugins/transfer-delegate.md

+ 162 - 4
src/pages/core/plugins/transfer-delegate.md

@@ -10,8 +10,13 @@ The `Transfer Delegate` Plugin is a `Owner Managed` plugin that allows the autho
 
 The Transfer Plugin will work in areas such as:
 
-- Escrowless sale of the Asset.
-- Gaming scenario where the user swaps/loses their asset based on an event.
+- Escrowless sale of the Asset: Transfer NFTs directly to buyers without needing an escrow account
+- Gaming scenario where the user swaps/loses their asset based on an event: Automatically transfer assets when game events occur
+- Subscription services: Transfer NFTs as part of a subscription service
+
+{% callout title="Warning!" %}
+The transfer delegate authority is temporary and will be reset upon asset transfer.
+{% /callout %}
 
 ## Works With
 
@@ -24,7 +29,11 @@ The Transfer Plugin will work in areas such as:
 
 The Transfer Plugin doesn't contain any arguments to pass in.
 
-## Adding the Transfer Plugin to an Asset
+## Functions
+
+### Add Transfer Delegate Plugin to an Asset
+
+The `addPlugin` command adds the Transfer Delegate Plugin to an Asset. This plugin allows a delegate to transfer the Asset at any time.
 
 {% dialect-switcher title="Adding a Transfer Plugin to an MPL Core Asset" %}
 {% dialect title="JavaScript" id="js" %}
@@ -37,7 +46,7 @@ const assetAddress = publicKey('11111111111111111111111111111111')
 const delegate = publicKey('22222222222222222222222222222222')
 
 await addPlugin(umi, {
-  asset: asset.publicKey,
+  asset: assetAddress,
   plugin: {
     type: 'TransferDelegate',
     authority: { type: 'Address', address: delegate },
@@ -47,6 +56,18 @@ await addPlugin(umi, {
 
 {% /dialect %}
 
+{% dialect title="Rust CPI" id="rust-cpi" %}
+```rust
+AddPluginV1CpiBuilder::new(ctx.accounts.mpl_core_program)
+    .asset(ctx.accounts.asset)
+    .collection(Some(ctx.accounts.collection))
+    .authority(Some(ctx.accounts.authority))
+    .payer(ctx.accounts.payer)
+    .plugin(Plugin::TransferDelegate(TransferDelegate {}))
+    .invoke();
+```
+{% /dialect %}
+
 {% dialect title="Rust" id="rust" %}
 
 ```rust
@@ -93,3 +114,140 @@ pub async fn add_transfer_delegate_plugin() {
 
 {% /dialect %}
 {% /dialect-switcher %}
+
+### Delegate the Transfer Authority
+
+The `approvePluginAuthority` command delegates the transfer authority to a different address. This allows another address to transfer the Asset while maintaining ownership.
+
+{% dialect-switcher title="Delegate the Transfer Authority" %}
+{% dialect title="JavaScript" id="js" %}
+
+```ts
+import { publicKey } from '@metaplex-foundation/umi'
+import { approvePluginAuthority } from '@metaplex-foundation/mpl-core'
+
+const asset = publicKey("11111111111111111111111111111111");
+const collection = publicKey("22222222222222222222222222222222");
+const delegateAddress = publicKey("33333333333333333333333333333333");
+
+await approvePluginAuthority(umi, {
+  asset: asset,
+  collection: collection,
+  plugin: { type: "TransferDelegate" },
+  newAuthority: { type: "Address", address: delegateAddress },
+}).sendAndConfirm(umi);
+```
+
+{% /dialect %}
+
+{% dialect title="Rust CPI" id="rust-cpi" %}
+```rust
+ApprovePluginAuthorityV1CpiBuilder::new(ctx.accounts.mpl_core_program)
+    .asset(ctx.accounts.asset)
+    .collection(Some(ctx.accounts.collection))
+    .authority(Some(ctx.accounts.authority))
+    .payer(ctx.accounts.payer)
+    .plugin_type(PluginType::TransferDelegate)
+    .new_authority(PluginAuthority::Address { address: ctx.accounts.new_authority.key() })
+    .invoke()?;
+```
+{% /dialect %}
+
+{% dialect title="Rust" id="rust" %}
+```rust
+use mpl_core::{
+    instructions::ApprovePluginAuthorityV1Builder,
+    types::{PluginAuthority, PluginType},
+};
+use solana_client::nonblocking::rpc_client;
+use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::Transaction};
+use std::str::FromStr;
+
+pub async fn approve_plugin_authority() {
+    let rpc_client = rpc_client::RpcClient::new("https://api.devnet.solana.com".to_string());
+
+    let authority = Keypair::new();
+    let new_authority = Keypair::new();
+    let asset = Pubkey::from_str("11111111111111111111111111111111").unwrap();
+    let collection = Pubkey::from_str("2222222222222222222222222222222").unwrap();
+
+    let approve_plugin_authority_ix = ApprovePluginAuthorityV1Builder::new()
+        .asset(asset)
+        // If the Asset is part of a collection, the collection must be passed in
+        .collection(Some(collection))
+        .authority(Some(authority.pubkey()))
+        .payer(authority.pubkey())
+        .plugin_type(PluginType::TransferDelegate)
+        .new_authority(PluginAuthority::Address { address: new_authority.pubkey() })
+        .instruction();
+
+    let signers = vec![&authority];
+
+    let last_blockhash = rpc_client.get_latest_blockhash().await.unwrap();
+
+    let approve_plugin_authority_tx = Transaction::new_signed_with_payer(
+        &[approve_plugin_authority_ix],
+        Some(&authority.pubkey()),
+        &signers,
+        last_blockhash,
+    );
+
+    let res = rpc_client
+        .send_and_confirm_transaction(&approve_plugin_authority_tx)
+        .await
+        .unwrap();
+
+    println!("Signature: {:?}", res);
+}
+```
+{% /dialect %}
+{% /dialect-switcher %}
+
+### Transferring an Asset As Delegate
+
+The `transfer` instruction transfers an Asset to another address using the transfer delegate authority.
+
+{% dialect-switcher title="Transfer an MPL Core Asset" %}
+{% dialect title="JavaScript" id="js" %}
+
+```ts
+import {
+  fetchAsset,
+  fetchCollection,
+  transfer,
+} from "@metaplex-foundation/mpl-core";
+import { publicKey } from "@metaplex-foundation/umi";
+
+// Asset ID you wish to transfer
+const assetId = publicKey("11111111111111111111111111111111");
+
+// Fetch the Asset
+const assetItem = await fetchAsset(umi, assetId);
+
+// Fetch collection if Asset is apart of collection
+const collectionItem =
+    assetItem.updateAuthority.type == "Collection" &&
+    assetItem.updateAuthority.address
+      ? await fetchCollection(umi, assetItem.updateAuthority.address)
+      : undefined;
+
+// Transfer the Core NFT Asset
+const { signature } = await transfer(umi, {
+    asset: assetItem,
+    newOwner: publicKey("22222222222222222222222222222222"),
+    collection: collectionItem,
+  })
+  .sendAndConfirm(umi);
+
+{% /dialect %}
+
+{% dialect title="Rust CPI" id="rust-cpi" %}
+```rust
+TransferV1CpiBuilder::new(&ctx.accounts.mpl_core_program.to_account_info())
+    .asset(&ctx.accounts.asset.to_account_info())
+    .new_owner(&ctx.accounts.new_owner.to_account_info())
+    .payer(&ctx.accounts.payer.to_account_info())
+    .authority(Some(&ctx.accounts.delegate_authority.to_account_info()))
+    .system_program(&ctx.accounts.system_program.to_account_info())
+    .invoke()?;
+```