说说eosio.token

本文介绍了如何使用EOSIO.token合约创建及管理代币,包括部署合约、发行、空投、转账等操作,并探讨了合约中的关键函数如create、issue和transfer。此外,还提出了一种查询剩余发行量的方法以及对合约源码的初步分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、eosio.token合约的请用

  • 使用账户 hily 部署系统的 eosio.token 合约
    $ cleos set contract hily build/contracts/eosio.token -p hily
  • 使用账户 hily 创建 HH 币,发行总量100000个

    $ cleos push action hily create ‘[“hily”,”100000.0000 HH”,1,1,1]’ -p hily

  • 向账户 hily 空投100个 HH

    $ cleos push action hily issue ‘[“hily”,”100.0000 HH”,”memo”]’ -p hily

  • 查询账户 hily 的余额

    $ cleos get table hily hily accounts

  • 从账户 hily 转账10 HHjay

    $ cleos push action hily transfer ‘[“hily”,”jay”,”10.0000 HH”,”memo”]’ -p hily

  • 查看账户 jay 的余额

    $ cleos get table hily jay accounts

  • 使用 hily 部署 token 合约后,可以像上面一样, hily 自己创建一个 HH 币,同时账户 jay 也可以创建他的 JAY

    $ cleos push action hily create ‘[“jay”,”10000.0000 JAY”,1,1,1]’ -p hily

  • 空投 jayJAY 币到 jack 时,要注意命令中各个账户的使用

    $ cleos push action hily issue ‘[“jack”,”20.0000 JAY”,”memo”]’ -p jay

  • 这时查看 jack 账户时,可以看到拥有的 JAY 币余额

    $ cleos get table hily jack accounts

  • 如果 jack 除了拥有 JAY 币外,还有拥有其他币,则上面的命令的结果将会显示 jack 不同的币的余额。

二、问题

  • 比如上面我们将会发行10000个 JAY 币,并且空投了20个到 jack 账户,那么我们如何获得 JAY 币的剩余发行量(10000 - 20 = 9980)?

三、eosio.token源码分析

构造函数:使用 hily 账户部署 token 合约时( cleos set contract hily build/contracts/eosio.token -p hily ), hily 将传给 self ,而该 self 传到父类 contract 中时,将会存到到父类的 _self 属性中。

token( account_name self ):contract(self){}

create函数:创建加密币,对应到这个命令 cleos push action hily create '["hily","100000.0000 HH",1,1,1]' -p hily

void token::create( account_name issuer,
                    asset        maximum_supply,
                    uint8_t      issuer_can_freeze,
                    uint8_t      issuer_can_recall,
                    uint8_t      issuer_can_whitelist )
{
    // 这里的 _self 就是部署合约时的 hily ,所以上面的 create 命令需要加上 "-p hily"
    require_auth( _self );

    auto sym = maximum_supply.symbol;
    eosio_assert( sym.is_valid(), "invalid symbol name" ); // 这里检查代币符合是否合法,比如上面的"HH"
    eosio_assert( maximum_supply.is_valid(), "invalid supply");
    eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");  // 这里检查代币的数量必须大于0,比如上面是100000.0000

    stats statstable( _self, sym.name() );
    auto existing = statstable.find( sym.name() );  // 根据代币的符号,比如上面命令中的"HH",在合约中进行查找
    eosio_assert( existing == statstable.end(), "token with symbol already exists" );  // 保证在这个合约中之前没有创建过这样的代币("HH")

    // 把参数存放到statstable中
    statstable.emplace( _self, [&]( auto& s ) {
       s.supply.symbol = maximum_supply.symbol;
       s.max_supply    = maximum_supply;
       s.issuer        = issuer;
       s.can_freeze    = issuer_can_freeze;
       s.can_recall    = issuer_can_recall;
       s.can_whitelist = issuer_can_whitelist;
    });
}

issue:空投或者发币cleos push action hily issue ‘[“jack“,”20.0000 JAY”,”memo”]’ -p jay

void token::issue( account_name to, asset quantity, string memo )
{
    print( "issue" );
    auto sym = quantity.symbol;
    eosio_assert( sym.is_valid(), "invalid symbol name" );  // 首先确保正确的代币

    auto sym_name = sym.name();
    stats statstable( _self, sym_name );
    auto existing = statstable.find( sym_name );
    eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" );  // 确保该代币,比如"JAY",是存在的
    const auto& st = *existing;

    require_auth( st.issuer );  // 通过代币"JAY"找到对应的发行者是"jay",所以上面的issue需要加上"-p jay"
    eosio_assert( quantity.is_valid(), "invalid quantity" );
    eosio_assert( quantity.amount > 0, "must issue positive quantity" );

    eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
    eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply");  // 确保空投的数量不能超过剩余的可发行量

    statstable.modify( st, 0, [&]( auto& s ) {
       s.supply += quantity;
    });

    // 这里有点意思,你会发现在这里jay账户会增加20 JAY,虽然上面的命令是空投20 JAY到jack账户
    add_balance( st.issuer, quantity, st, st.issuer );

    // 到这里的时候,因为to是jack,st.issue是jay,所以不相等
    if( to != st.issuer ) {
       // 这里call transfer的时候,就会先call sub_balance然后call sub_balance
       // 实作就是把jay账户减去20(因为上面加了20到jay,而实际需要加到jack的),然后把jack账户增加20 JAY
       SEND_INLINE_ACTION( *this, transfer, {st.issuer,N(active)}, {st.issuer, to, quantity, memo} );
    }
}

transfer:转账cleos push action hily transfer ‘[“jay”,”jack”,”10.0000 HH”,”memo”]’ -p jay

void token::transfer( account_name from,
                      account_name to,
                      asset        quantity,
                      string       /*memo*/ )
{
    print( "transfer from ", eosio::name{from}, " to ", eosio::name{to}, " ", quantity, "\n" );
    eosio_assert( from != to, "cannot transfer to self" );  // 杜绝自己给自己转账,每个人都这么干将会造成EOS拥堵
    require_auth( from );  // 在这里就可以知道上面的命令为什么加上"-p jay"了
    eosio_assert( is_account( to ), "to account does not exist");  // 检查账户合法性
    auto sym = quantity.symbol.name();
    stats statstable( _self, sym );
    const auto& st = statstable.get( sym );

    require_recipient( from );
    require_recipient( to );

    // 检查转账的数量和代币正常性
    eosio_assert( quantity.is_valid(), "invalid quantity" );
    eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
    eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );

    // 从from账户中减去指定的币额并加到to账户
    sub_balance( from, quantity, st );
    add_balance( to, quantity, st, from );
}

原文来自我的博客

### 关于Agent Token缓存机制 #### 实现方式 对于`agent token`的管理,尤其是像Instagram Basic Display API这样的服务,通常会采用一种混合式的缓存策略来确保token的有效性和及时更新。一方面,在应用层面可以通过集成诸如Redis这样的分布式缓存系统来存储和快速检索token;另一方面,则可以在本地使用Guava Cache或其他自定义的LocalCache解决方案作为第二级缓存[^1]。 当首次请求获取token时,如果在本地缓存中找不到有效条目,则向远程服务器发起认证请求,并将返回的新鲜token保存到两个级别的缓存中。为了防止过期问题,应当设置合理的TTL(Time To Live),使得接近失效时间前自动触发刷新流程,从而保证下次访问仍然能够获得有效的凭证[^2]。 此外,考虑到安全性因素,建议定期轮换密钥材料,并通过HTTPS协议传输敏感数据以保护通信链路的安全性[^4]。 #### 常见问题 - **Token过期处理不当**:未能正确判断token是否即将到期或已经过期,导致API调用失败。解决办法是在设计上预留足够的时间窗口用于提前续订token。 - **并发冲突**:多个实例几乎同时尝试更新相同的token资源,造成不必要的竞争条件。这可通过引入锁机制或者优化算法逻辑来缓解。 - **跨平台一致性维护困难**:不同环境下的配置差异可能导致某些地方无法正常工作。统一管理和分发配置文件有助于减轻此类困扰。 ```python import redis from google.common.cache import CacheBuilder import time # Redis client setup for distributed cache r = redis.Redis(host='localhost', port=6379, db=0) # Local Guava Cache with TTL of 5 minutes (in seconds) local_cache = CacheBuilder.newBuilder()\ .expireAfterWrite(300, TimeUnit.SECONDS)\ .build() def get_token(): # Try local cache first try: return local_cache.get('insta_token') except Exception as e: pass # Fallback to Redis if not found locally or expired token = r.get('insta_token') if not token: # Simulate fetching new token from external service print("Fetching new token...") token = "new_generated_token" # Store in both caches with appropriate TTLs r.setex('insta_token', 3600, token) # Set expiration after one hour local_cache.put('insta_token', token) return token.decode('utf-8') if isinstance(token, bytes) else token if __name__ == "__main__": while True: tok = get_token() print(f"Current token is {tok}") time.sleep(10) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值