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};
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!