风险提示:理性看待区块链,提高风险意识!
EOS钱包开发:如何买入或卖出RAM?
首页 > 币界资讯 > 竞争币新闻 2019-01-19 09:18:21

目标

  1. 如何获取全网RAM相关的公共数据
  2. 如何使用Bancor算法计算实时的RAM价格
  3. 如何购买RAM
  4. 如何卖出RAM

前言

现在我们能获取到了基于测试网络的账号的网络资源数据,现在我们就介绍如何交易RAM。

交易RAM的前提是我们需要知道它的价格,即买1KB内存需要花费多少EOS,卖1个EOS能获取多少内存。这就需要我们去链上查询数据库获取相应的实时的数据,再进行计算拿到单价。下面我们来一步步实现,最后展示在项目中的相应源码。

一、获取全网RAM数量

全网RAM数量的数据是存在数据库中的,需要使用eosjs库的getTableRows方法获取,或者RPC的chain/get_table_rows接口获取。下面会有eosjs进行交易,所以本章我们统一使用eosjs访问数据,可以到官网查看eosjs-api接口文档。

首先访问主网中RAM的数量。

Eos = require('eosjs')eosconfig = {
    httpEndpoint: 'https://node1.zbeos.com',
    chainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906',    // keyProvider: privatekeyList, // WIF string or array of keys..
    expireInSeconds: 60,
    broadcast: true,
    verbose: false, // API activity
    sign: true
},
eos = Eos(eosconfig)eos.getTableRows(true,"eosio","eosio","global").then(result => {
    console.log(result)
})
输出如下
{ rows:
   [ { max_block_net_usage: 1048576,
       target_block_net_usage_pct: 1000,
       max_transaction_net_usage: 524288,
       base_per_transaction_net_usage: 12,
       net_usage_leeway: 500,
       context_free_discount_net_usage_num: 20,
       context_free_discount_net_usage_den: 100,
       max_block_cpu_usage: 200000,
       target_block_cpu_usage_pct: 2000,
       max_transaction_cpu_usage: 150000,
       min_transaction_cpu_usage: 100,
       max_transaction_lifetime: 3600,
       deferred_trx_expiration_window: 600,
       max_transaction_delay: 3888000,
       max_inline_action_size: 4096,
       max_inline_action_depth: 4,
       max_authority_depth: 6,
       max_ram_size: '88414727168',
       total_ram_bytes_reserved: '49777052734',
       total_ram_stake: '26261375993',
       last_producer_schedule_update: '2018-11-05T06:57:51.000',
       last_pervote_bucket_fill: '1541399606000000',
       pervote_bucket: 219209992,
       perblock_bucket: 36804696,
       total_unpaid_blocks: 95761,
       total_activated_stake: '4035546740321',
       thresh_activated_stake_time: '1529505892000000',
       last_producer_schedule_size: 21,
       total_producer_vote_weight: '24124687214114213888.00000000000000000',
       last_name_close: '2018-11-05T02:08:26.000' } ],
  more: false }
其中“max_ram_size“字段的数据就是全网RAM的数量,单位是bytes,那么转换为G,则结果为:88402589696/(1024*1024*1024)=82.34263134002686 G。获取方式如下:
eos.getTableRows(true,"eosio","eosio","global").then(result => {
    //ram总量,bytes转为G
    let ramTotal = result.rows[0].max_ram_size / (1024*1024*1024)  
})

二、获取RAM使用量、计算RAM价格

与获取RAM总量一样,我们使用eosjs库的getTableRows方法获取主网中RAM的使用量、消耗RAM的EOS数量,最后通过Bancor算法计算RAM价格。

eosconfig = {
    httpEndpoint: 'https://node1.zbeos.com',
    chainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906',    // keyProvider: privatekeyList, // WIF string or array of keys..
    expireInSeconds: 60,
    broadcast: true,
    verbose: false, // API activity
    sign: true
},
eos = Eos(eosconfig)eos.getTableRows(true, "eosio", "eosio", "rammarket").then(ramData => {
    console.log(ramData)
})

输出如下

9A5D836D-283E-40DC-B16A-38AFB4658E5E

  • 其中“base“字段里的“balance”数据就是全网RAM的使用量,单位是bytes。
  • “quote“字段里的“balance”数据就是消耗RAM的EOS数量。

下面根据Bancor算法算出RAM的价格

ramPrice = quote.balance / (base.balance / 1024)

Bancor协议是底层货币协议,通过区块链技术和智能合约为加密数字货币提供连续流动性和实现异步价格。

所以ramPrice的获取方式如下:

eos.getTableRows(true, "eosio", "eosio", "rammarket").then(ramData => {
    console.log(ramData)
    //RAM消耗的EOS数量
    let eosAmount = ramData.rows[0].quote.balance.split(" ")[0];
    //RAM使用量
    let ramAmount = ramData.rows[0].base.balance.split(" ")[0] / 1024;
    //RAM价格
    let ramPriceWithEOS = eosAmount / ramAmount
    console.log(eosAmount, ramAmount, ramPriceWithEOS);
})

三、买入RAM

买入RAM的API其实我们已经使用过了,在创建账号的时候我们为别人创建的账号就需要为它购买一定的RAM,现在我们在来单独调用购买的API。由于现在需要交易,所以会使用资源,因此我们重新配置一下eosconfig切换到测试网络进行测试。

eosconfig = {
    httpEndpoint:"http://jungle.cryptolions.io:18888",
    chainId: "038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca", // 32 byte (64 char) hex string
    keyProvider: ["5HqCj7sg4K2xZ1KD5sSH38kuJkKGqfE1wSGiLL3M599ajacVmTs"], 
    expireInSeconds: 60,
    broadcast: true,
    verbose: false, // API activity
    sign: true
},eos = Eos(eosconfig)eos.getTableRows(true, "eosio", "eosio", "rammarket").then(ramData => {
    console.log(ramData)
    //RAM消耗的EOS数量
    let eosAmount = ramData.rows[0].quote.balance.split(" ")[0];
    //RAM使用量
    let ramAmount = ramData.rows[0].base.balance.split(" ")[0] / 1024;
    //RAM价格
    let ramPriceWithEOS = eosAmount / ramAmount
    console.log(eosAmount, ramAmount, ramPriceWithEOS);
})let account = "lixutest1111"
let ramAmount = 8*1024
async function buyRAM() {
    result = await eos.transaction(tr => {
        tr.buyrambytes({
            payer: account,
            receiver: account,
            bytes: ramAmount
        })
    })
    console.log(result)
}
buyRAM()

在运行之前先记录下来账号“lixutest1111”的网络资源数据。

16922119-4D43-4E58-BE15-1A91CD49EAC1

运行后看到价格是0.07576784159120188 EOS/KB

1A22A00B-D38E-481B-BA95-43991A32D684

代码中是买了8KB的RAM,那我们计算一下,需要花费多少EOS,其实很简单

8KB * 0.07576784159120188 EOS/KB = 0.6061EOS
那我们再计算一下账号“lixutest1111”现在的EOS可用余额和RAM总量是多少
78.7959 - 0.6061 = 78.1898EOS
13.30 + 8 = 21.30KB

计算好以后我们再看看现在账号“lixutest1111”的在链上的资源数据是多少。

6C676B46-83CF-4BB3-A84B-FCE67370E536

可以发现计算的结果和链上的结果有了一定的偏差,这是因为RAM价格会随着市场波动而变化,所以导致结果有一点点偏差,这是不可避免的。另外我们在购买RAM的时候,需要输入的是EOS数量,然后根据RAM价格转换成需要购买的RAM大小,再进行交易。

四、卖出RAM

卖出RAM需要用到另外一个方法 sellram

eosconfig = {
    httpEndpoint: "http://jungle.cryptolions.io:18888",
    chainId: "038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca", // 32 byte (64 char) hex string
    keyProvider: ["5HqCj7sg4K2xZ1KD5sSH38kuJkKGqfE1wSGiLL3M599ajacVmTs"],
    expireInSeconds: 60,
    broadcast: true,
    verbose: false, // API activity
    sign: true
},    eos = Eos(eosconfig)eos.getTableRows(true, "eosio", "eosio", "rammarket").then(ramData => {
    console.log(ramData)
    //RAM消耗的EOS数量
    let eosAmount = ramData.rows[0].quote.balance.split(" ")[0];
    //RAM使用量
    let ramAmount = ramData.rows[0].base.balance.split(" ")[0] / 1024;
    //RAM价格
    let ramPriceWithEOS = eosAmount / ramAmount
    console.log(eosAmount, ramAmount, ramPriceWithEOS);
})let account = "lixutest1111"
let ramAmount = 8*1024
async function sellRAM() {
    result = await eos.transaction(tr => {
        tr.sellram({
            account: account,
            bytes: ramAmount
        })
    })
    console.log(result)
}
sellRAM()

运行后看到价格是0.0757692783033557 EOS/KB,确实与上一次获取到的价格有点偏差。

6E4A29E6-5782-4632-8D14-65287FD5775D

这里就不花时间作计算了,大家可以在根据价格与出售量计算在做比较。重新查看账号“lixutest1111”的EOS数量多了0.6,RAM内存减少了8KB。

88594B86-16C7-46F6-A2D6-4104CA9E36EA

五、项目源码

1. controllers/netResource.js

在controllers文件夹下新建netResource.js文件,实现获取全局RAM数据与买入卖出RAM的功能。

let { success, fail } = require("../utils/myUtils")
let myUtils = require("../utils/myUtils")
let walletModel = require("../models/wallet")async function getRamInfo() {
    ramData = await eos.getTableRows(true, "eosio", "eosio", "rammarket")
    //RAM消耗的EOS数量
    let eosAmount = ramData.rows[0].quote.balance.split(" ")[0];
    //RAM使用量
    let ramAmount = ramData.rows[0].base.balance.split(" ")[0] / 1024;
    //RAM价格
    let ramPriceWithEOS = eosAmount / ramAmount
    console.log(eosAmount, ramAmount, ramPriceWithEOS);
    return {
        ramUsed: ramAmount / (1024 * 1024),
        ramPrice: ramPriceWithEOS,
    }
}module.exports = {
    netResourceGetRAMInfo: async (ctx) => {
        console.log(ctx.request.body)
        let { wallet, password } = ctx.request.body
        //获取钱包里面所有的私钥配置EOSJS
        let privatekeyList = await walletModel.getWalletPrivatekeyList(wallet, password)
        eos = myUtils.getEOSJS(privatekeyList)        let ramData = await eos.getTableRows(true, "eosio", "eosio", "global")
        //ram总量,bytes转为G
        let ramTotal = ramData.rows[0].max_ram_size / (1024 * 1024 * 1024)
        console.log(ramTotal);        let ramInfo = await getRamInfo()
        ctx.body = success({
            ramPrice: ramInfo.ramPrice,
            ramTotal: ramTotal,
            ramAvailable: ramTotal - ramInfo.ramUsed,
        })
    },    netResourceTransactionRAM: async (ctx) => {
        console.log(ctx.request.body)
        let { amount, transaction_type, account, wallet, password } = ctx.request.body
        //获取钱包里面所有的私钥配置EOSJS
        let privatekeyList = await walletModel.getWalletPrivatekeyList(wallet, password)
        eos = myUtils.getEOSJS(privatekeyList)        let result
        if (transaction_type == '1') {
            //买RAM
            console.log("买RAM")
            let ramInfo = await getRamInfo()
            let ramAmount = parseInt((amount / ramInfo.ramPrice) * 1024)
            console.log("ramAmount:", ramAmount)
            result = await eos.transaction(tr => {
                tr.buyrambytes({
                    payer: account,
                    receiver: account,
                    bytes: ramAmount
                })
            })
        } else {
            //卖RAM
            console.log("卖RAM")
            let ramAmount = parseInt(amount*1024)
            result = await eos.transaction(tr => {
                tr.sellram({
                    account: account,
                    bytes: ramAmount 
                })
            })
        }        console.log("data:", result)
        if (result.broadcast) {
            ctx.body = success("ok")
        } else {
            ctx.body = fail("error")
        }
    }}

2. router/router.js

将获取全局RAM数据与买入卖出RAM的接口绑定到路由。

......
let netresourceController = require("../controllers/netResource")//网络资源
router.post("/net_resource/ram/info", netresourceController.netResourceGetRAMInfo)
router.post("/net_resource/ram/transaction", netresourceController.netResourceTransactionRAM)

3. views/netResource.html

编辑views文件夹下的netResource.html文件,实现RAM交易的表单显示。

......<div class="interactive">
    <form id="ram-transaction">
        <input type="radio" id="ram-transaction-buy" name="transaction_type" value="1" checked="checked">
        <label for="ram-transaction-buy">买入</label>        <input type="radio" id="ram-transaction-sell" name="transaction_type" value="2"  checked>
        <label for="ram-transaction-sell">卖出</label>
        <br>        <div>全网内存:<span id="ram-total"></span></div>
        <div>内存价格:<span id="ram-price"></span> EOS/KB</div>        <label>数量:</label>
        <input type="text" name="amount" placeholder="请输入EOS数量"><br>        <input type="text" name="account" hidden="hidden">
        <input type="text" name="wallet" hidden="hidden">
        <input type="text" name="password" hidden="hidden">
        <button type="submit" id="ram-transaction-button">买入</button>
    </form>
</div>......

4. static/js/netResource.js

对全局RAM数据与买入卖出RAM的表单进行网络请求处理与页面渲染。

$(document).ready(function () {
    ......    $("input[name=account][hidden=hidden]").val(currentAccount)
    let currentwallet = localStorage.getItem("currentwallet")
    let walletPassword = localStorage.getItem(currentwallet)
    $("input[name=wallet][hidden=hidden]").val(currentwallet)
    $("input[name=password][hidden=hidden]").val(walletPassword)    $("input[name=transaction_type]").change(function () {
        if (this.value == 1) {
            $("#ram-transaction-button").text("买入")
            $("input[name=amount]").attr({"placeholder":"请输入EOS数量"})
        } else {
            $("#ram-transaction-button").text("卖出")
            $("input[name=amount]").attr({"placeholder":"请输入RAM(KB)数量"})        }
    })    //ram全局数据
    $.post("/net_resource/ram/info", { "account": currentAccount }, function (res, status) {
        console.log(status + JSON.stringify(res))
        if (res.code == 0) {
            $("#ram-total").text(res.data.ramAvailable.toFixed(2) + " GB / " + res.data.ramTotal.toFixed(2) + "GB")
            $("#ram-price").text(res.data.ramPrice.toFixed(6))
        }
    })    //交易RAM
    $("#ram-transaction").validate({
        rules: {
            amount: {required: true,},
        },
        messages: {
            name: {required: "请输入要交易的数量",},
        },
        submitHandler: function (form) {
            $(form).ajaxSubmit({
                url: "/net_resource/ram/transaction",
                type: "post",
                dataType: "json",
                success: function (res, status) {
                    console.log(status + JSON.stringify(res))
                    if (res.code == 0) {
                        alert("交易成功")
                        location.reload() 
                    } else {
                        alert("交易失败")
                    }
                },
                error: function (res, status) {
                    console.log(status + JSON.stringify(res))
                    alert(res.data)
                }
            });
        }
    })
})

六、项目效果

504E68A9-7F20-4789-9668-58154FA21490

项目源码Github地址

版权声明:博客中的文章版权归博主所有,未经授权禁止转载,转载请联系作者(微信:lixu1770105)取得同意并注明出处。

未经授权禁止转载、改编,转载请注明出处!

上一篇: 比特币跌破3800美元 看看大佬们怎么看熊市
下一篇: 比特币改变世界:六个故事,讲完比特币十年
推荐专栏
web3首席知识博主
一位相信价值投资的币圈KOL。稳定盈利的缠论野生交易员 #BTC行情分析师 #价值投资 #链上数据分析
爱Web 3,爱生活,爱科技,爱炒币的老韭菜
热门币种
更多
币种
价格
24H涨跌幅
BTC比特币
¥268,024.08
37,553.64 USDT
+6.07%
ETH以太坊
¥14,691.72
2,058.50 USDT
+4.21%
USDT泰达币
¥7.24
1.01 USDT
+0.17%
BNB币安币
¥1,805.40
252.96 USDT
+3.65%
XRP瑞波币
¥4.61
0.64540 USDT
+2.82%
SOLSolana
¥476.14
66.71 USDT
+17.55%
USDC
¥7.14
0.99980 USDT
-0.03%
OKBOK币
¥425.82
59.66 USDT
+2.62%
ADA艾达币
¥2.73
0.38280 USDT
+7.41%
DOGE狗狗币
¥0.54600
0.07651 USDT
+5.42%
热搜币种
更多
币种
价格
24H涨跌幅
dYdX
¥30.18
4.1641 USDT
+10.02%
Filecoin
¥38.47
5.3092 USDT
+9.82%
FTX Token
¥26.75
3.6913 USDT
+1.89%
PancakeSwap
¥19.42
2.6795 USDT
+6.23%
Solana
¥483.46
66.7138 USDT
+17.55%
奇亚
¥197.65
27.2746 USDT
+3.28%
Yield Guild Games
¥3.08
0.4249 USDT
+4.17%
Conflux
¥1.24
0.1716 USDT
+7.72%
火必积分
¥21.85
3.015 USDT
+5%
Terra Classic
¥0.00
8.271E-5 USDT
+3.18%
阿童木
¥71.55
9.8728 USDT
+9.82%
Flow
¥5.26
0.7253 USDT
+9.02%
最新快讯
更多
去中心化隐私协议HinkalProtocol完成410万美元融资
2023-11-16 11:37:54
一个休眠730天的钱包在5小时前向Kraken存入120万枚DYDX
2023-11-16 11:31:30
中国人民银行:将在后续工作中研究数字人民币免手续费
2023-11-16 11:30:13
Binance全仓、逐仓杠杆新增BEAMX资产
2023-11-16 11:28:31
韩国国家养老基金购买近2000万美元的Coinbase股票,浮盈40%
2023-11-16 11:22:05
韩国国家养老基金购买价值近2000万美元的Coinbase股票,浮盈40%
2023-11-16 11:22:05
韩国国家养老基金已买入Coinbase价值约2000万美元的股票
2023-11-16 11:22:05
下载币界网APP