前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >8.MOVE从入门到实战-发布代币到Aptos网络并调用合约

8.MOVE从入门到实战-发布代币到Aptos网络并调用合约

作者头像
Tiny熊
发布2022-11-07 11:13:44
1.1K0
发布2022-11-07 11:13:44
举报

本文作者:木头[1]

代币合约

合约参数

保存代币余额
代码语言:javascript
复制
struct Coin has store {
    value : u128,
}
地址对印余额数据
代码语言:javascript
复制
struct CoinStore has key {
    coin : Coin,
}
代币基础信息
代码语言:javascript
复制
struct CoinInfo has key {
    // 名称
    name: string::String,
    // 符号
    symbol: string::String,
    // 精度
    decimals: u8,
    // 总发行量
    supply: u128,
    // 已发行量
    cap: u128,
}

assert 错误信息定义

assert只能给定 u64 错误信息,全局错误定义

代码语言:javascript
复制
// 账户已经注册
const THE_ACCOUNT_HAS_BEEN_REGISTERED : u64 = 1;
// 无效的令牌所有者
const INVALID_TOKEN_OWNER : u64 = 2;
// 账户未注册
const THE_ACCOUNT_IS_NOT_REGISTERED : u64 = 3;
// 余额不足
const INSUFFICIENT_BALANCE : u64 = 4;
// 代币信息已发布
const ECOIN_INFO_ALREADY_PUBLISHED : u64 = 5;
// 超过总供应量
const EXCEEDING_THE_TOTAL_SUPPLY : u64 = 6;

合约查询方法

查询代币余额
代码语言:javascript
复制
public fun getBalance(owner: address) : u128 acquires CoinStore{
    // 确定帐户是否已注册
    assert!(is_account_registered(owner), THE_ACCOUNT_IS_NOT_REGISTERED);
    // 返回余额
    borrow_global<CoinStore>(owner).coin.value
}
查询帐户是否已注册
代码语言:javascript
复制
public fun is_account_registered(account_addr : address) : bool{
    exists<CoinStore>(account_addr)
}

合约公共方法

增加地址余额

代码语言:javascript
复制
fun deposit(account_addr : address, coin : Coin) acquires CoinStore {
    // 确定该帐户是否已注册
    assert!(is_account_registered(account_addr), THE_ACCOUNT_IS_NOT_REGISTERED);
    // 转账之前余额
    let balance = getBalance(account_addr);
    // 获取可变资源余额
    let balance_ref = &mut borrow_global_mut<CoinStore>(account_addr).coin.value;
    // 更新余额
    *balance_ref = balance + coin.value;
    // 销毁资源
    let Coin { value:_ } = coin;
}

减少地址余额

代码语言:javascript
复制
fun withdraw(account_addr : address, amount : u128) : Coin acquires CoinStore {
    // 确定该帐户是否已注册
    assert!(is_account_registered(account_addr), THE_ACCOUNT_IS_NOT_REGISTERED);
    // 转账之前余额
    let balance = getBalance(account_addr);
    // 余额是否足够
    assert!(balance >= amount, INSUFFICIENT_BALANCE);
    // 获取可变资源余额
    let balance_ref = &mut borrow_global_mut<CoinStore>(account_addr).coin.value;
    // 更新余额
    *balance_ref = balance - amount;
    // 返回余额资源
    Coin { value: amount }
}

合约执行函数

初始化代币信息

代码语言:javascript
复制
public entry fun initialize(address : &signer, name : vector<u8>, symbol : vector<u8>, decimals : u8, supply : u128)  {
    // 是否有权限初始化代币信息
    assert!(signer::address_of(address) == MODULE_OWNER, INVALID_TOKEN_OWNER);
    // 确定是否已初始化(防止重复初始化)
    assert!(!exists<CoinInfo>(MODULE_OWNER), ECOIN_INFO_ALREADY_PUBLISHED);
    // 创建令牌信息
    move_to(address, CoinInfo{name : string::utf8(name), symbol : string::utf8(symbol), decimals, supply, cap : 0});
}

address:调用用者,name:名称,symbol:符号,decimals:精度,supply:总发行量

注册账号(在交易之前必须先注册账号)

代码语言:javascript
复制
public entry fun register(address : &signer) {
    let account = signer::address_of(address);
    // 确定该帐户是否已注册(防止重复注册)
    assert!(!exists<CoinStore>(account), THE_ACCOUNT_HAS_BEEN_REGISTERED);
    // 初始化账号
    move_to(address, CoinStore{ coin : Coin{ value : 0 } });
}

铸币

代码语言:javascript
复制
public entry fun mint(owner : &signer,to : address,amount : u128) acquires CoinStore,CoinInfo{
    // 是否有权限铸币
    assert!(signer::address_of(owner) == MODULE_OWNER, INVALID_TOKEN_OWNER);
    // 是否超过总发行量
    assert!(borrow_global<CoinInfo>(MODULE_OWNER).cap + amount <= borrow_global<CoinInfo>(MODULE_OWNER).supply,EXCEEDING_THE_TOTAL_SUPPLY);
    // 收款人增加余额
    deposit(to, Coin { value : amount });
    // 增加发行总量
    let cap = &mut borrow_global_mut<CoinInfo>(MODULE_OWNER).cap;
    *cap = *cap + amount;
}

owner:必须为模块拥有者才能有权限铸币,to:给 to 地址铸币,amount:铸币数量

转账

代码语言:javascript
复制
public entry fun transfer(from : &signer, to : address, amount : u128) acquires CoinStore {
    // 先扣除账号余额
    let coin = withdraw(signer::address_of(from), amount);
    // 增加账号余额
    deposit(to, coin);
}

销毁

代码语言:javascript
复制
public entry fun burn(owner : &signer, amount : u128) acquires CoinStore,CoinInfo {
    // 是否有权限销毁
    assert!(signer::address_of(owner) == MODULE_OWNER, INVALID_TOKEN_OWNER);
    // 扣除账号余额
    let coin = withdraw(signer::address_of(owner), amount);
    let Coin { value: amount } = coin;
    // 减少已发行量
    let cap = &mut borrow_global_mut<CoinInfo>(MODULE_OWNER).cap;
    *cap = *cap - amount;
    // 减少总发行量
    let supply = &mut borrow_global_mut<CoinInfo>(MODULE_OWNER).supply;
    *supply = *supply - amount;
}

Typescript 脚本

生成账号脚本

account_script.ts

代码语言:javascript
复制
//节点URL  REST API地址
export const NODE_URL = "https://fullnode.devnet.aptoslabs.com";
//水龙头URL
export const FAUCET_URL = "https://faucet.devnet.aptoslabs.com";

//生成账号接口
import { AptosAccount, MaybeHexString } from "aptos";

//Aptos客户端 水龙头客户端
import { AptosClient, FaucetClient } from "aptos";

//创建节点客户端
const client = new AptosClient(NODE_URL);

//查询主链币余额
export async function accountBalance(accountAddress: MaybeHexString): Promise<number | null> {
  const resource = await client.getAccountResource(accountAddress, "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
  if (resource == null) {
    return null;
  }

  return parseInt((resource.data as any)["coin"]["value"]);
}

//主方法
async function main() {
  //创建帐户
  const account = new AptosAccount();

  console.log("\n=== 地址 ===");
  console.log(
    `地址: ${account.address()} key种子: ${Buffer.from(account.signingKey.secretKey).toString("hex").slice(0, 64)}`,
  );
  //水龙头领取代币
  const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);
  await faucetClient.fundAccount(account.address(), 50000);

  console.log("\n=== 账户余额 ===");
  console.log(`${account.address()}余额: ${await accountBalance(account.address())}`);
}

if (require.main === module) {
  main();
}

调用合约脚本

coin_script.ts

代码语言:javascript
复制
import assert from "assert";
import fs from "fs";
import { AptosAccount, AptosClient, TxnBuilderTypes, BCS, MaybeHexString, HexString, FaucetClient } from "aptos";

//节点URL  REST API地址
export const NODE_URL = "https://fullnode.devnet.aptoslabs.com";
//水龙头URL
export const FAUCET_URL = "https://faucet.devnet.aptoslabs.com";

// 创建aptos客户端
const client = new AptosClient(NODE_URL);

// 查询APT代币余额
export async function getAccountBalance(accountAddress: MaybeHexString): Promise<number | null> {
  const resource = await client.getAccountResource(accountAddress, "0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>");
  if (resource == null) {
    return null;
  }

  return parseInt((resource.data as any)["coin"]["value"]);
}

//发布模块
export async function publishModule(accountFrom: AptosAccount, moduleHex: string): Promise<string> {
  const moudleBundlePayload = new TxnBuilderTypes.TransactionPayloadModuleBundle(
    new TxnBuilderTypes.ModuleBundle([new TxnBuilderTypes.Module(new HexString(moduleHex).toUint8Array())]),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    moudleBundlePayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const transactionRes = await client.submitSignedBCSTransaction(bcsTxn);

  return transactionRes.hash;
}

//注册代币账号=>初始化账号
async function registerCoin(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(`${contractAddress.toString()}::coin`, "register", [], []),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}

// 初始化token信息
async function initializeCoin(contractAddress: HexString, accountFrom: AptosAccount): Promise<string> {
  // 总发行量
  const supply = new BCS.Serializer();
  supply.serializeU128(1000);

  // 精度
  const decimals = new BCS.Serializer();
  decimals.serializeU8(0);

  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(
      `${contractAddress}::coin`,
      "initialize",
      [],
      [BCS.bcsSerializeStr("CPI Coin"), BCS.bcsSerializeStr("CPI"), decimals.getBytes(), supply.getBytes()],
    ),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}

//铸币
async function mintCoin(
  contractAddress: HexString,
  accountFrom: AptosAccount,
  receiverAddress: HexString,
  amount: number,
): Promise<string> {
  // 发行量
  const cap = new BCS.Serializer();
  cap.serializeU128(amount);

  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(
      `${contractAddress.toString()}::coin`,
      "mint",
      [],
      [BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(receiverAddress.hex())), cap.getBytes()],
    ),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}

//转账
async function transfer(
  contractAddress: HexString,
  accountFrom: AptosAccount,
  to: HexString,
  amount: number,
): Promise<string> {
  const amo = new BCS.Serializer();
  amo.serializeU128(amount);

  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(
      `${contractAddress.toString()}::coin`,
      "transfer",
      [],
      [BCS.bcsToBytes(TxnBuilderTypes.AccountAddress.fromHex(to.hex())), amo.getBytes()],
    ),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}

// 销毁
async function burn(contractAddress: HexString, accountFrom: AptosAccount, amount: number): Promise<string> {
  const amo = new BCS.Serializer();
  amo.serializeU128(amount);

  const entryFunctionPayload = new TxnBuilderTypes.TransactionPayloadEntryFunction(
    TxnBuilderTypes.EntryFunction.natural(`${contractAddress.toString()}::coin`, "burn", [], [amo.getBytes()]),
  );

  const [{ sequence_number: sequenceNumber }, chainId] = await Promise.all([
    client.getAccount(accountFrom.address()),
    client.getChainId(),
  ]);

  const rawTxn = new TxnBuilderTypes.RawTransaction(
    TxnBuilderTypes.AccountAddress.fromHex(accountFrom.address()),
    BigInt(sequenceNumber),
    entryFunctionPayload,
    1000n,
    1n,
    BigInt(Math.floor(Date.now() / 1000) + 10),
    new TxnBuilderTypes.ChainId(chainId),
  );

  const bcsTxn = AptosClient.generateBCSTransaction(accountFrom, rawTxn);
  const pendingTxn = await client.submitSignedBCSTransaction(bcsTxn);

  return pendingTxn.hash;
}

//查询代币余额
async function getBalance(contractAddress: HexString, accountFrom: AptosAccount): Promise<string | number | any> {
  try {
    const resource = await client.getAccountResource(accountFrom.address(), `${contractAddress}::coin::CoinStore`);
    return parseInt((resource.data as any)["coin"]["value"]);
  } catch (_) {
    return 0;
  }
}

//查询代币信息
async function getCoinInfo(contractAddress: HexString): Promise<string | number | any> {
  try {
    const resource = await client.getAccountResource(contractAddress, `${contractAddress}::coin::CoinInfo`);
    return resource;
  } catch (_) {
    return 0;
  }
}

async function main() {

  assert(process.argv.length == 3, "Expecting an argument that points to the moon coin module");

  //创建客户端
  const client = new AptosClient(NODE_URL);
  const account = new AptosAccount(
    new HexString("3a64b8d0478799c570fb540fc2aabc917604b72f7cd44c75d8df4629e5af58ce").toUint8Array(),
  );
  console.log(`模块拥有者 ${account.address()}余额: ${await getAccountBalance(account.address())}APT`);

  //创建水龙头客户端
  const faucetClient = new FaucetClient(NODE_URL, FAUCET_URL);

  // 发布模块
  const modulePath = process.argv[2];
  const moduleHex = fs.readFileSync(modulePath).toString("hex");
  console.log("\n==========发布模块========");
  let txHash = await publishModule(account, moduleHex);
  console.log("发布模块:" + txHash);
  await client.waitForTransaction(txHash);

  console.log("\n==========初始化token信息========");
  txHash = await initializeCoin(account.address(), account);
  console.log("初始化token信息Hash:" + txHash);
  await client.waitForTransaction(txHash);

  console.log("\n==========token信息========");
  let coinInfo: CoinInfo = await getCoinInfo(account.address());
  console.log(`模块类型:${coinInfo.type}`);
  console.log(`名称:${coinInfo.data.name}`);
  console.log(`符号:${coinInfo.data.symbol}`);
  console.log(`精度:${coinInfo.data.decimals}`);
  console.log(`总发行量:${coinInfo.data.supply}`);
  console.log(`已发行量:${coinInfo.data.cap}`);

  console.log("\n==========创建测试账号A和B==========");
  const a = new AptosAccount();
  console.log(`a地址: ${a.address()}`);

  const b = new AptosAccount();
  console.log(`b地址: ${b.address()}`);

  // 领取gas费
  await faucetClient.fundAccount(a.address(), 5000);
  await faucetClient.fundAccount(b.address(), 5000);

  //注册代币账号=>初始化账号
  console.log("\n==========注册代币账号========");
  txHash = await registerCoin(account.address(), a);
  console.log("a注册Hash:" + txHash);
  await client.waitForTransaction(txHash);
  txHash = await registerCoin(account.address(), b);
  console.log("b注册Hash:" + txHash);
  await client.waitForTransaction(txHash);
  txHash = await registerCoin(account.address(), account);
  console.log("模块拥有者注册Hash:" + txHash);
  await client.waitForTransaction(txHash);

  //铸币
  console.log("\n==========铸造100个代币给A账号========");
  txHash = await mintCoin(account.address(), account, a.address(), 100);
  console.log("管理员给A账号铸币Hash:" + txHash);
  await client.waitForTransaction(txHash);
  let aBalance = await getBalance(account.address(), a);
  console.log(`a余额:` + aBalance);

  //转账
  console.log("\n==========A账号转账50个代币给B账号========");
  txHash = await transfer(account.address(), a, b.address(), 50);
  console.log("转账Hash:" + txHash);
  await client.waitForTransaction(txHash);
  //查询余额
  aBalance = await getBalance(account.address(), a);
  console.log(`a余额:` + aBalance);
  let bBalance = await getBalance(account.address(), b);
  console.log(`b余额:` + bBalance);

  // 销毁
  console.log("\n==========B账号转账50个代币给模块拥有者========");
  txHash = await transfer(account.address(), b, account.address(), 50);
  console.log("转账Hash:" + txHash);
  await client.waitForTransaction(txHash);
  //查询余额
  aBalance = await getBalance(account.address(), a);
  console.log(`a余额:` + aBalance);
  bBalance = await getBalance(account.address(), b);
  console.log(`b余额:` + bBalance);
  let accountBalance = await getBalance(account.address(), account);
  console.log(`模块拥有者余额:` + accountBalance);
  //开始销毁
  console.log("\n==========销毁50个代币========");
  txHash = await burn(account.address(), account, 50);
  console.log("销毁Hash:" + txHash);
  await client.waitForTransaction(txHash);
  aBalance = await getBalance(account.address(), a);
  console.log(`a余额:` + aBalance);
  bBalance = await getBalance(account.address(), b);
  console.log(`b余额:` + bBalance);
  accountBalance = await getBalance(account.address(), account);
  console.log(`模块拥有者余额:` + accountBalance);
  coinInfo = await getCoinInfo(account.address());
  console.log(`总发行量:${coinInfo.data.supply}`);
  console.log(`已发行量:${coinInfo.data.cap}`);
}

if (require.main === module) {
  main();
}

// 代币信息
interface CoinInfo {
  type: string;
  data: Data;
}

interface Data {
  cap: string; //已发行量
  decimals: number; //精度
  name: string; //名称
  symbol: string; //符号
  supply: string; //总发行量
}

发布并调用合约

1.调用 account_script.ts 生成合约部署账号

代码语言:javascript
复制
$ node --loader ts-node/esm account_script.ts
=== 地址 ===
地址: 0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93 key种子: 3a64b8d0478799c570fb540fc2aabc917604b72f7cd44c75d8df4629e5af58ce

=== 账户余额 ===
0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93余额: 50000

2.复制地址到合约项目 Move.toml 配置

代码语言:javascript
复制
[addresses]
std = "0x1"
CoinToken = "0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93"

生成 mv

代码语言:javascript
复制
$ aptos move compile --package-dir . --named-addresses CoinToken=0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93
{
  "Result": [
    "E13C36E921448A601F2DE9DC5341525CA6619A44E1444F302FBA37FB39C5CF93::coin"
  ]
}

3.复制合约项目 mv 到脚本项目根目录

4.复制账号的种子到 coin_script.ts 的 main

5.调用 coin_script.ts 脚本

代码语言:javascript
复制
$ node --loader ts-node/esm coin_script.ts coin.mv

模块拥有者0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93余额: 50000APT

==========发布模块========
发布模块:0x6d81ba53b5fe50d4d0a73022c8c4c2a8383d81e72768ea9e6066b425c93d5888

==========初始化token信息========
初始化token信息Hash:0x5a62958de06aa7407425c541a83c746e97a66ae427d8ac40a59ab8711c977fa4

==========token信息========
模块类型:0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93::coin::CoinInfo
名称:CPI Coin
符号:CPI
精度:0
总发行量:1000
已发行量:0

==========创建测试账号A和B==========
a地址: 0x17f086d99a1fe096c397880173ae2356b95d63423ff75a6627827b3fc760e224
b地址: 0x922164511c6046c223e90653ebc26a68b0b914114a0c382f1c113319e394826b

==========注册代币账号========
a注册Hash:0x0256d8b19cd7551f582573ab8e4968ea7a0a25fed2ca901619187f1830d5966e
b注册Hash:0x837d60bc99e8143eb21370c6f1eb6cf9d7b0cbfddb3405c18697072cb4e8442e
模块拥有者注册Hash:0xdd93a94a785f0f85d38b143305880114314ef3ca30ad4d0e7e78a2063f9f514e

==========铸造100个代币给A账号========
管理员给A账号铸币Hash:0x60dbc50c4c61626a32c632a9a997ed9a147101c89c0387b3a57d93fc7ec31ddf
a余额:100

==========A账号转账50个代币给B账号========
转账Hash:0xa3a477466c687ddb86d80cfbff36b645f08edb31175ff9d85df80ab6719d1749
a余额:50
b余额:50

==========B账号转账50个代币给模块拥有者========
转账Hash:0x85205f4c94f922bd8b62c8a4cd68bbe4ea3a7581ffa05e9c81e2a12401028357
a余额:50
b余额:0
模块拥有者余额:50

==========销毁50个代币========
销毁Hash:0x529be7b0f235d8af769d7c00a8b78455ccdbee9e6d9b758a9538e349b0a1ce6f
a余额:50
b余额:0
模块拥有者余额:0
总发行量:950
已发行量:50

区块浏览器:https://explorer.devnet.aptos.dev/account/0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93[2]

参考资料

[1]

木头: https://learnblockchain.cn/people/3015

[2]

https://explorer.devnet.aptos.dev/account/0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93: https://explorer.devnet.aptos.dev/account/0xe13c36e921448a601f2de9dc5341525ca6619a44e1444f302fba37fb39c5cf93

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 代币合约
    • 合约参数
      • 保存代币余额
      • 地址对印余额数据
      • 代币基础信息
    • assert 错误信息定义
      • 合约查询方法
        • 查询代币余额
        • 查询帐户是否已注册
    • 合约公共方法
      • 增加地址余额
        • 减少地址余额
        • 合约执行函数
          • 初始化代币信息
            • 注册账号(在交易之前必须先注册账号)
              • 铸币
                • 转账
                  • 销毁
                  • Typescript 脚本
                    • 生成账号脚本
                      • 调用合约脚本
                      • 发布并调用合约
                        • 参考资料
                        相关产品与服务
                        访问管理
                        访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档