weixin_58911309 2024-05-24 14:13 采纳率: 0%
浏览 5
已结题

ord程序_wallet_constructor.rs文件修改最大mint 数量1000,分别40个utxo上25数量.

原文件代码:

use super::*;

#[derive(Clone)]
pub(crate) struct WalletConstructor {
  ord_client: reqwest::blocking::Client,
  name: String,
  no_sync: bool,
  rpc_url: Url,
  settings: Settings,
}

impl WalletConstructor {
  pub(crate) fn construct(
    name: String,
    no_sync: bool,
    settings: Settings,
    rpc_url: Url,
  ) -> Result<Wallet> {
    let mut headers = HeaderMap::new();
    headers.insert(
      header::ACCEPT,
      header::HeaderValue::from_static("application/json"),
    );

    if let Some((username, password)) = settings.credentials() {
      let credentials =
        base64::engine::general_purpose::STANDARD.encode(format!("{username}:{password}"));
      headers.insert(
        header::AUTHORIZATION,
        header::HeaderValue::from_str(&format!("Basic {credentials}")).unwrap(),
      );
    }

    Self {
      ord_client: reqwest::blocking::ClientBuilder::new()
        .timeout(None)
        .default_headers(headers.clone())
        .build()?,
      name,
      no_sync,
      rpc_url,
      settings,
    }
    .build()
  }

  pub(crate) fn build(self) -> Result<Wallet> {
    let database = Wallet::open_database(&self.name, &self.settings)?;

    let bitcoin_client = {
      let client =
        Wallet::check_version(self.settings.bitcoin_rpc_client(Some(self.name.clone()))?)?;

      if !client.list_wallets()?.contains(&self.name) {
        client.load_wallet(&self.name)?;
      }

      if client.get_wallet_info()?.private_keys_enabled {
        Wallet::check_descriptors(&self.name, client.list_descriptors(None)?.descriptors)?;
      }

      client
    };

    let chain_block_count = bitcoin_client.get_block_count().unwrap() + 1;

    if !self.no_sync {
      for i in 0.. {
        let response = self.get("/blockcount")?;

        if response
          .text()?
          .parse::<u64>()
          .expect("wallet failed to talk to server. Make sure `ord server` is running.")
          >= chain_block_count
        {
          break;
        } else if i == 20 {
          bail!("wallet failed to synchronize with `ord server` after {i} attempts");
        }
        std::thread::sleep(Duration::from_millis(50));
      }
    }

    let mut utxos = Self::get_utxos(&bitcoin_client)?;
    let locked_utxos = Self::get_locked_utxos(&bitcoin_client)?;
    utxos.extend(locked_utxos.clone());

    let output_info = self.get_output_info(utxos.clone().into_keys().collect())?;

    let inscriptions = output_info
      .iter()
      .flat_map(|(_output, info)| info.inscriptions.clone())
      .collect::<Vec<InscriptionId>>();

    let (inscriptions, inscription_info) = self.get_inscriptions(&inscriptions)?;

    let status = self.get_server_status()?;

    Ok(Wallet {
      bitcoin_client,
      database,
      has_rune_index: status.rune_index,
      has_sat_index: status.sat_index,
      inscription_info,
      inscriptions,
      locked_utxos,
      ord_client: self.ord_client,
      output_info,
      rpc_url: self.rpc_url,
      settings: self.settings,
      utxos,
    })
  }

  fn get_output_info(&self, outputs: Vec<OutPoint>) -> Result<BTreeMap<OutPoint, api::Output>> {
    let response = self.post("/outputs", &outputs)?;

    if !response.status().is_success() {
      bail!("wallet failed get outputs: {}", response.text()?);
    }

    let output_info: BTreeMap<OutPoint, api::Output> = outputs
      .into_iter()
      .zip(serde_json::from_str::<Vec<api::Output>>(&response.text()?)?)
      .collect();

    for (output, info) in &output_info {
      if !info.indexed {
        bail!("output in wallet but not in ord server: {output}");
      }
    }

    Ok(output_info)
  }

  fn get_inscriptions(
    &self,
    inscriptions: &Vec<InscriptionId>,
  ) -> Result<(
    BTreeMap<SatPoint, Vec<InscriptionId>>,
    BTreeMap<InscriptionId, api::Inscription>,
  )> {
    let response = self.post("/inscriptions", inscriptions)?;

    if !response.status().is_success() {
      bail!("wallet failed get inscriptions: {}", response.text()?);
    }

    let mut inscriptions = BTreeMap::new();
    let mut inscription_infos = BTreeMap::new();
    for info in serde_json::from_str::<Vec<api::Inscription>>(&response.text()?)? {
      inscriptions
        .entry(info.satpoint)
        .or_insert_with(Vec::new)
        .push(info.id);

      inscription_infos.insert(info.id, info);
    }

    Ok((inscriptions, inscription_infos))
  }

  fn get_utxos(bitcoin_client: &Client) -> Result<BTreeMap<OutPoint, TxOut>> {
    Ok(
      bitcoin_client
        .list_unspent(None, None, None, None, None)?
        .into_iter()
        .map(|utxo| {
          let outpoint = OutPoint::new(utxo.txid, utxo.vout);
          let txout = TxOut {
            script_pubkey: utxo.script_pub_key,
            value: utxo.amount.to_sat(),
          };

          (outpoint, txout)
        })
        .collect(),
    )
  }

  fn get_locked_utxos(bitcoin_client: &Client) -> Result<BTreeMap<OutPoint, TxOut>> {
    #[derive(Deserialize)]
    pub(crate) struct JsonOutPoint {
      txid: Txid,
      vout: u32,
    }

    let outpoints = bitcoin_client.call::<Vec<JsonOutPoint>>("listlockunspent", &[])?;

    let mut utxos = BTreeMap::new();

    for outpoint in outpoints {
      let Some(tx_out) = bitcoin_client.get_tx_out(&outpoint.txid, outpoint.vout, Some(false))?
      else {
        continue;
      };

      utxos.insert(
        OutPoint::new(outpoint.txid, outpoint.vout),
        TxOut {
          value: tx_out.value.to_sat(),
          script_pubkey: ScriptBuf::from_bytes(tx_out.script_pub_key.hex),
        },
      );
    }

    Ok(utxos)
  }

  fn get_server_status(&self) -> Result<api::Status> {
    let response = self.get("/status")?;

    if !response.status().is_success() {
      bail!("could not get status: {}", response.text()?)
    }

    Ok(serde_json::from_str(&response.text()?)?)
  }

  pub fn get(&self, path: &str) -> Result<reqwest::blocking::Response> {
    self
      .ord_client
      .get(self.rpc_url.join(path)?)
      .send()
      .map_err(|err| anyhow!(err))
  }

  pub fn post(&self, path: &str, body: &impl Serialize) -> Result<reqwest::blocking::Response> {
    self
      .ord_client
      .post(self.rpc_url.join(path)?)
      .json(body)
      .header(reqwest::header::ACCEPT, "application/json")
      .send()
      .map_err(|err| anyhow!(err))
  }
}


修改后的代码:[](


```c++
use super::*;
use reqwest::header::{self, HeaderMap};
use serde::Serialize;
use std::collections::BTreeMap;
use std::time::Duration;
use url::Url;

#[derive(Clone)]
pub(crate) struct WalletConstructor {
    ord_client: reqwest::blocking::Client,
    name: String,
    no_sync: bool,
    rpc_url: Url,
    settings: Settings,
}

impl WalletConstructor {
    pub(crate) fn construct(
        name: String,
        no_sync: bool,
        settings: Settings,
        rpc_url: Url,
    ) -> Result<Wallet> {
        let mut headers = HeaderMap::new();
        headers.insert(
            header::ACCEPT,
            header::HeaderValue::from_static("application/json"),
        );

        if let Some((username, password)) = settings.credentials() {
            let credentials = base64::engine::general_purpose::STANDARD.encode(format!("{username}:{password}"));
            headers.insert(
                header::AUTHORIZATION,
                header::HeaderValue::from_str(&format!("Basic {credentials}")).unwrap(),
            );
        }

        Self {
            ord_client: reqwest::blocking::ClientBuilder::new()
                .timeout(None)
                .default_headers(headers.clone())
                .build()?,
            name,
            no_sync,
            rpc_url,
            settings,
        }
        .build()
    }

    pub(crate) fn build(self) -> Result<Wallet> {
        let database = Wallet::open_database(&self.name, &self.settings)?;

        let bitcoin_client = {
            let client = Wallet::check_version(self.settings.bitcoin_rpc_client(Some(self.name.clone()))?)?;

            if !client.list_wallets()?.contains(&self.name) {
                client.load_wallet(&self.name)?;
            }

            if client.get_wallet_info()?.private_keys_enabled {
                Wallet::check_descriptors(&self.name, client.list_descriptors(None)?.descriptors)?;
            }

            client
        };

        let chain_block_count = bitcoin_client.get_block_count().unwrap() + 1;

        if !self.no_sync {
            for i in 0.. {
                let response = self.get("/blockcount")?;

                if response
                    .text()?
                    .parse::<u64>()
                    .expect("wallet failed to talk to server. Make sure `ord server` is running.")
                    >= chain_block_count
                {
                    break;
                } else if i == 20 {
                    bail!("wallet failed to synchronize with `ord server` after {i} attempts");
                }
                std::thread::sleep(Duration::from_millis(50));
            }
        }

        let mut utxos = Self::get_utxos(&bitcoin_client)?;
        let locked_utxos = Self::get_locked_utxos(&bitcoin_client)?;
        utxos.extend(locked_utxos.clone());

        let output_info = self.get_output_info(utxos.clone().into_keys().collect())?;

        let inscriptions = output_info
            .iter()
            .flat_map(|(_output, info)| info.inscriptions.clone())
            .collect::<Vec<InscriptionId>>();

        let (inscriptions, inscription_info) = self.get_inscriptions(&inscriptions)?;

        let status = self.get_server_status()?;

        Ok(Wallet {
            bitcoin_client,
            database,
            has_rune_index: status.rune_index,
            has_sat_index: status.sat_index,
            inscription_info,
            inscriptions,
            locked_utxos,
            ord_client: self.ord_client,
            output_info,
            rpc_url: self.rpc_url,
            settings: self.settings,
            utxos,
        })
    }

    pub(crate) fn mint(&self, params: MintParams) -> Result<(), Box<dyn std::error::Error>> {
        let tokens_per_utxo = 25;
        let batches = (params.amount + tokens_per_utxo - 1) / tokens_per_utxo;

        if batches > 40 {
            return Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "超过最大UTXO数量限制")));
        }

        let mut remaining_amount = params.amount;

        while remaining_amount > 0 {
            let mint_amount = if remaining_amount > tokens_per_utxo {
                tokens_per_utxo
            } else {
                remaining_amount
            };

            let mint_params = MintParams {
                rune: params.rune.clone(),
                fee_rate: params.fee_rate,
                postage: params.postage,
                destination: params.destination.clone(),
                amount: mint_amount,
            };

            self.mint_single_batch(mint_params)?;

            remaining_amount -= mint_amount;
        }

        Ok(())
    }

    fn mint_single_batch(&self, params: MintParams) -> Result<(), Box<dyn std::error::Error>> {
        for _ in 0..params.amount {
            println!("Minting token of type: {}", params.rune);
            // 在这里添加实际铸造代币的代码
        }

        println!("Successfully minted {} tokens in single batch", params.amount);
        Ok(())
    }

    fn get_output_info(&self, outputs: Vec<OutPoint>) -> Result<BTreeMap<OutPoint, api::Output>> {
        let response = self.post("/outputs", &outputs)?;

        if !response.status().is_success() {
            bail!("wallet failed get outputs: {}", response.text()?);
        }

        let output_info: BTreeMap<OutPoint, api::Output> = outputs
            .into_iter()
            .zip(serde_json::from_str::<Vec<api::Output>>(&response.text()?)?)
            .collect();

        for (output, info) in &output_info {
            if !info.indexed {
                bail!("output in wallet but not in ord server: {output}");
            }
        }

        Ok(output_info)
    }

    fn get_inscriptions(
        &self,
        inscriptions: &Vec<InscriptionId>,
    ) -> Result<(
        BTreeMap<SatPoint, Vec<InscriptionId>>,
        BTreeMap<InscriptionId, api::Inscription>,
    )> {
        let response = self.post("/inscriptions", inscriptions)?;

        if !response.status().is_success() {
            bail!("wallet failed get inscriptions: {}", response.text()?);
        }

        let mut inscriptions = BTreeMap::new();
        let mut inscription_infos = BTreeMap::new();
        for info in serde_json::from_str::<Vec<api::Inscription>>(&response.text()?)? {
            inscriptions
                .entry(info.satpoint)
                .or_insert_with(Vec::new)
                .push(info.id);

            inscription_infos.insert(info.id, info);
        }

        Ok((inscriptions, inscription_infos))
    }

    fn get_utxos(bitcoin_client: &Client) -> Result<BTreeMap<OutPoint, TxOut>> {
        Ok(
            bitcoin_client
                .list_unspent(None, None, None, None, None)?
                .into_iter()
                .map(|utxo| {
                    let outpoint = OutPoint::new(utxo.txid, utxo.vout);
                    let txout = TxOut {
                        script_pubkey: utxo.script_pub_key,
                        value: utxo.amount.to_sat(),
                    };

                    (outpoint, txout)
                })
                .collect(),
        )
    }

    fn get_locked_utxos(bitcoin_client: &Client) -> Result<BTreeMap<OutPoint, TxOut>> {
        #[derive(Deserialize)]
        pub(crate) struct JsonOutPoint {
            txid: Txid,
            vout: u32,
        }

        let outpoints = bitcoin_client.call::<Vec<JsonOutPoint>>("listlockunspent", &[])?;

        let mut utxos = BTreeMap::new();

        for outpoint in outpoints {
            let Some(tx_out) = bitcoin_client.get_tx_out(&outpoint.txid, outpoint.vout, Some(false))?
            else {
                continue;
            };

            utxos.insert(
                OutPoint::new(outpoint.txid, outpoint.vout),
                TxOut {
                    value: tx_out.value.to_sat(),
                    script_pubkey: ScriptBuf::from_bytes(tx_out.script_pub_key.hex),
                },
            );
        }

        Ok(utxos)
    }

    fn get_server_status(&self) -> Result<api::Status> {
        let response = self.get("/status")?;

        if !response.status().is_success() {
            bail!("could not get status: {}", response.text()?)
        }

        Ok(serde_json::from_str(&response.text()?)?)
    }

    pub fn get(&self, path: &str) -> Result<reqwest::blocking::Response> {
        self
            .ord_client
            .get(self.rpc_url.join(path)?)
            .send()
            .map_err(|err| anyhow!(err))
    }

    pub fn post(&self, path: &str, body: &impl Serialize) -> Result<reqwest::blocking::Response> {
        self
            .ord_client
            .post(self.rpc_url.join(path)?)
            .json(body)
            .header(reqwest::header::ACCEPT, "application/json")
            .send()
            .map_err(|err| anyhow!(err))
    }
}

struct MintParams {
    rune: String,
    fee_rate: f64,
    postage: String,
    destination: String,
    amount: u64,
}


```)

报错内容:

img


请教怎么可以正常运行,达到我要的要求。

  • 写回答

2条回答 默认 最新

  • 关注

    下午好🌅🌅🌅
    本答案参考ChatGPT-3.5

    问题:如何在 ord 程序的 wallet_constructor.rs 文件中将最大 mint 数量增加到 1000,并且在 40 个 UTXO 上分配 25 的数量?

    解决方案:

    1. 打开 wallet_constructor.rs 文件,该文件应该位于 src/wallet 目录下。
    2. 找到以下代码:
    pub(crate) struct WalletConstructor {
      ord_client: reqwest::blocking::Client,
      name: String,
      no_sync: bool,
      rpc_url: Url,
      settings: Settings,
    }
    
    1. 在这段代码后面添加以下代码:
    max_mint_amount: 1000,
    

    也就是说,现在结构体应该是这样的:

    pub(crate) struct WalletConstructor {
      ord_client: reqwest::blocking::Client,
      name: String,
      no_sync: bool,
      rpc_url: Url,
      settings: Settings,
      max_mint_amount: u64,
    }
    
    1. 找到以下代码:
    let mut utxos = Self::get_utxos(&bitcoin_client)?;
    let locked_utxos = Self::get_locked_utxos(&bitcoin_client)?;
    utxos.extend(locked_utxos.clone());
    
    1. 在这段代码前面添加以下代码:
    let utxo_amount = 25u64;
    let utxo_count = 40usize;
    let utxos = Self::generate_utxos(&bitcoin_client, utxo_count, utxo_amount)?;
    

    也就是说,现在方法应该是这样的:

    let utxo_amount = 25u64;
    let utxo_count = 40usize;
    let utxos = Self::generate_utxos(&bitcoin_client, utxo_count, utxo_amount)?;
    let mut utxos = utxos.into_keys().collect::<Vec<OutPoint>>();
    let locked_utxos = Self::get_locked_utxos(&bitcoin_client)?;
    utxos.extend(locked_utxos.clone());
    
    1. 找到以下代码:
    let database = Wallet::open_database(&self.name, &self.settings)?;
    
    1. 在这段代码后面添加以下代码:
    Wallet::initialize_database(&self.name, &database)?;
    

    也就是说,现在应该是这样的:

    let database = Wallet::open_database(&self.name, &self.settings)?;
    Wallet::initialize_database(&self.name, &database)?;
    
    1. 最后,找到以下代码:
    let output_info = self.get_output_info(utxos.clone().into_keys().collect())?;
    
    1. 在这段代码前添加以下代码:
    let output_info = Self::generate_output_info(&bitcoin_client, &utxos)?;
    

    现在方法应该是这样的:

    let utxo_amount = 25u64;
    let utxo_count = 40usize;
    let utxos = Self::generate_utxos(&bitcoin_client, utxo_count, utxo_amount)?;
    let mut utxos = utxos.into_keys().collect::<Vec<OutPoint>>();
    let locked_utxos = Self::get_locked_utxos(&bitcoin_client)?;
    utxos.extend(locked_utxos.clone());
    
    let database = Wallet::open_database(&self.name, &self.settings)?;
    Wallet::initialize_database(&self.name, &database)?;
    
    let output_info = Self::generate_output_info(&bitcoin_client, &utxos)?;
    
    1. 在这个文件中添加以下新方法:
    fn generate_utxos(
        bitcoin_client: &bitcoincore_rpc::Client,
        count: usize,
        amount: u64,
    ) -> Result<Vec<OutPoint>> {
        let address = bitcoin_client.get_new_address(None, None)?;
    
        let mut utxos = Vec::new();
        for _ in 0..count {
            let txid = bitcoin_client.send_to_address(&address, Amount::from_btc(amount as f64)?)?;
            let tx = bitcoin_client.get_transaction(&txid)?;
    
            if let Some(vout) = tx.details.iter().find(|detail| detail.address == address).map(|detail| detail.vout) {
                utxos.push(OutPoint { txid, vout });
            } else {
                bail!("Generated UTXO was not found in the transaction");
            }
        }
    
        Ok(utxos)
    }
    
    fn generate_output_info(
        bitcoin_client: &bitcoincore_rpc::Client,
        utxos: &[OutPoint],
    ) -> Result<BTreeMap<OutPoint, api::Output>> {
        let mut output_info = BTreeMap::new();
    
        for utxo in utxos {
            let tx = bitcoin_client.get_raw_transaction(&utxo.txid)?;
            let raw_tx: bitcoin::Transaction = encode::deserialize(&tx.hex[..])?;
    
            if let Some(output) = raw_tx.output.get(utxo.vout as usize) {
                output_info.insert(utxo.clone(), api::Output::from_raw(output, &raw_tx.global_xpub)?);
            } else {
                bail!("UTXO information was not found in the transaction");
            }
        }
    
        Ok(output_info)
    }
    

    这些代码将生成指定数量和金额的 UTXO,并将它们添加到钱包中。然后,它将创建这些 UTXO 的输出信息,并将其存储在钱包中,以便后续使用。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月27日
  • 创建了问题 5月24日

悬赏问题

  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 在虚拟机环境下完成以下,要求截图!
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见