sui模拟pumpfun实现(1)Suimove在线发布coin技术探讨
move语言发布coin,需要编写代码, 提供一个otw ,每个coin是一个模块
// For Move coding conventions, see
// https://docs.sui.io/concepts/sui-move-concepts/conventions
module coin_simple::template {
    use sui::coin::{Self};
    use sui::url::{Self,Url};
    use std::ascii;
    use coin_manager::coin_manager;
    /// The OTW for the Coin
    public struct TEMPLATE has drop {}
    const DECIMALS: u8 = 9;
    const SYMBOL: vector<u8> = b"SYMBOL_TEMPLATE";
    const NAME: vector<u8> = b"COIN_NAME_TEMPLATE";
    const DESCRIPTION: vector<u8> = b"COIN_DESCRIPTION_TEMPLATE";
    const URL: vector<u8> = b"IMAGE_URL_TEMPLATE";
    /// Init the Coin
    fun init(witness: TEMPLATE, ctx: &mut TxContext) {
        let urlStr = ascii::string(URL);// 这个模版代码是未来会替换常量的,为了避免编译器优化,定义变量来获取内容
        let image_url:Option<Url> =  if (urlStr.length() > 0 ){  option::some(url::new_unsafe(urlStr))  } else{ option::none()};
        let (treasury, metadata) = coin::create_currency(
            witness, DECIMALS, SYMBOL, NAME, DESCRIPTION,image_url, ctx
        );
       //这是为了未来管理coin,提供一个管理模块
        coin_manager::register_coin(treasury,metadata,ctx);
    }
    #[test_only]
    public fun init_for_test( ctx: &mut TxContext) {
        let witness = TEMPLATE{};
        init(witness, ctx);
    }
}1) 生成一个模版工程
2) 网页上接收用户输入的coin的定制参数
3) 模版工程里面替换掉相关参数
需要用到 move_bytecode_template 库
4) 通过typescript发布新coin到sui链.
生成合约的二进制代码
sui move build --dump-bytecode-as-base64  >coin_bytecode.json读取二进制代码
import module_bytes from './coin_bytecode.json'
function readCoinTemplateBytes() : [ Uint8Array,string[]]{
  let bytecode : Uint8Array =  fromBase64(module_bytes.modules[0]);
  return [bytecode,module_bytes.dependencies];
}
修改二进制代码
export async function publishCoin(params : PublishCoinParams,  signer : Keypair) : Promise<PublishResult>{
  let publishResult : PublishResult = {isSucc:true};
  let [bytecode,deps] = readCoinTemplateBytes();
  let updated = template.update_identifiers(bytecode, {
      "TEMPLATE": params.module_name.toUpperCase(),
      "template": params.module_name
  });
  // Update DECIMALS
  updated = template.update_constants(
      updated,
      bcs.u8().serialize(params.decimal).toBytes(), // new value
      bcs.u8().serialize(9).toBytes(), // current value
      'U8', // type of the constant
  );
  // Update SYMBOL
  updated = template.update_constants(
      updated,
      bcs.string().serialize(params.symbol).toBytes(), // new value
      bcs.string().serialize('SYMBOL_TEMPLATE').toBytes(), // current value
      'Vector(U8)', // type of the constant
  );
  // Update NAME
  updated = template.update_constants(
      updated,
      bcs.string().serialize(params.coin_name).toBytes(), // new value
      bcs.string().serialize('COIN_NAME_TEMPLATE').toBytes(), // current value
      'Vector(U8)', // type of the constant
  );
  // Update desc
  updated = template.update_constants(
      updated,
      bcs.string().serialize(params.desc).toBytes(), // new value
      bcs.string().serialize('COIN_DESCRIPTION_TEMPLATE').toBytes(), // current value
      'Vector(U8)', // type of the constant
  );
  // Update URL
  let url = params.imageUrl ? params.imageUrl : '';
  updated = template.update_constants(
      updated,
      bcs.string().serialize(url).toBytes(), // new value
      bcs.string().serialize('IMAGE_URL_TEMPLATE').toBytes(), // current value
      'Vector(U8)', // type of the constant
  );
  const operator = signer.getPublicKey().toSuiAddress();
  let tx = new Transaction();
  let arr = updated as unknown as number[];
  let modules :number [][] = [];
  modules.push(arr)
  const [upgradeCap] = tx.publish({ modules, dependencies:deps });
  tx.transferObjects([upgradeCap], operator);
  tx.setGasBudget(1e8);
  let config = env.config();
  const suiClient = new SuiClient({ url: getFullnodeUrl(config.env) });    
  let balance = await suiClient.getBalance({owner:operator});
  const result = await suiClient.signAndExecuteTransaction({
      signer: signer,
      transaction: tx,
      options: {
          showEffects: true,
          showObjectChanges : true,
          ///showObjectChanges:true,
          showEvents:true
      },
      requestType: 'WaitForLocalExecution',
  });修改 module
module.exports.__inited = false;
module.exports.init = function(buffer){
    const wasmModule = new WebAssembly.Module(buffer);
    const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
    wasm = wasmInstance.exports;
    module.exports.__wasm = wasm;
    module.exports.__inited = true;
}
module.exports.isInited = function(){
    return module.exports.__inited;
}客户端js 下载wasm,初始化wasm
const init_url = async function(wasmUrl : string,useGzip : boolean){
  if(template.isInited()) return;
  try {
      const fetchUrl = useGzip ? wasmUrl.replace('wasm','gz') : wasmUrl;
      // 下载 WASM 文件
      const response = await fetch(fetchUrl);
      const buffer = await response.arrayBuffer();
      // 如果是 Gzip 文件,需要解压
      let wasmBuffer = buffer;
      if (useGzip) {
          const ds = new DecompressionStream('gzip');
          const stream = new Response(buffer).body!.pipeThrough(ds);
          wasmBuffer = await new Response(stream).arrayBuffer();
      }
      template.init(wasmBuffer);
  } catch (error) {
      console.error('Error loading or running WASM:', error);
  }
}
export async function init_template(wasmUrl : string,supportGzip : boolean) {
try{                                
    await init_url(wasmUrl,supportGzip);
}
catch(error){
    return     {errMsg  : `fail to init_url for wasm:{wasmUrl}`,
                isSucc : true}
}
return {isSucc:true};
} 
                如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!