亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用Node.js和NoSQL開發加密貨幣應用程序

發布時間:2021-12-29 10:14:05 來源:億速云 閱讀:152 作者:iii 欄目:互聯網科技

這篇文章主要介紹“怎么用Node.js和NoSQL開發加密貨幣應用程序”,在日常操作中,相信很多人在怎么用Node.js和NoSQL開發加密貨幣應用程序問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用Node.js和NoSQL開發加密貨幣應用程序”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

我們要在這里改變一下。到目前為止,我們已經在NoSQL數據庫中完成了面向帳戶的操作。另一個重要方面是交易。例如,也許用戶X為BTC存入一些美元貨幣,而用戶Y進行提款。我們需要存儲和查詢該交易信息。

API端點函數將保存交易數據,但我們仍然可以查詢它。

getAccountBalance(account) {
    var statement = "SELECT SUM(tx.satoshis) AS balance FROM " + this.bucket._name + " AS tx WHERE tx.type = 'transaction' AND tx.account = $account";
    var query = Couchbase.N1qlQuery.fromString(statement);
    return new Promise((resolve, reject) => {
        this.bucket.query(query, { "account": account }, (error, result) => {
            if(error) {
                reject({ "code": error.code, "message": error.message });
            }
            resolve({ "balance": result[0].balance });
        });
    });
}

給定一個帳戶,我們希望獲得特定用戶的帳戶余額。

等一下,讓我們退后一步,因為我們不是已經創建了一些帳戶余額功能嗎?從技術上講,我們做了,但這些功能用于檢查錢包余額,而不是帳戶余額。

這是我的一些經驗變成灰色區域的地方。每次發送比特幣時,都會收取費用,有時費用相當昂貴。當你存款時,將錢轉入你的錢包并不符合成本效益,因為這將收取礦工費。然后你將被收取撤回甚至轉賬的費用。那時你已經失去了大部分的比特幣。

相反,我認為交易所有一個類似于證券交易所貨幣市場賬戶的持有賬戶。你的帳戶中應該有資金的記錄,但從技術上講,它不在錢包中。如果你想要轉賬,則需要從應用程序地址而不是你的用戶地址進行轉賬。當你退出時,它只是被減去。

再說一次,我不知道這是否真的如何運作,但這就是我為了避免各處收費而采取的方式。

回到我們的getAccountBalance函數。我們正在處理每筆交易的總和。存款具有正值,而轉賬和取款具有負值。將這些信息匯總在一起可以為你提供準確的數字,不包括你的錢包余額。稍后我們將獲得一個錢包余額帳戶。

鑒于我們對帳戶余額知之甚少,我們可以嘗試從錢包中創建一個交易:

createTransactionFromAccount(account, source, destination, amount) {
    return new Promise((resolve, reject) => {
        this.getAddressBalance(source).then(sourceAddress => {
            if(sourceAddress.balanceSat < amount) {
                return reject({ "message": "Not enough funds in account." });
            }
            this.getPrivateKeyFromAddress(account, source).then(keypair => {
                this.getAddressUtxo(source).then(utxo => {
                    var transaction = new Bitcore.Transaction();
                    for(var i = 0; i < utxo.length; i++) {
                        transaction.from(utxo[i]);
                    }
                    transaction.to(destination, amount);
                    this.addAddress(account).then(change => {
                        transaction.change(change.address);
                        transaction.sign(keypair.secret);
                        resolve(transaction);
                    }, error => reject(error));
                }, error => reject(error));
            }, error => reject(error));
        }, error => reject(error));
    });
}

如果提供了源地址,目的地地址和金額,我們可以創建并簽署一個交易,以便稍后在比特幣網絡上廣播。

首先,我們得到有問題的源地址的余額。我們需要確保它有足夠的UTXO來滿足發送量預期。請注意,在此示例中,我們正在執行單個地址交易。如果你想變得復雜,可以在單個交易中從多個地址發送。我們不會在這里這樣做。如果我們的單個地址有足夠的資金,我們會獲得它的私鑰和UTXO數據。使用UTXO數據,我們可以創建比特幣交易,應用目的地地址和更改地址,然后使用我們的私鑰對交易進行簽名。可以廣播響應。

同樣地,假設我們想從我們的持有賬戶轉賬比特幣:

createTransactionFromMaster(account, destination, amount) {
    return new Promise((resolve, reject) => {
        this.getAccountBalance(account).then(accountBalance => {
            if(accountBalance.balance < amount) {
                reject({ "message": "Not enough funds in account." });
            }
            var mKeyPairs = this.getMasterKeyPairs();
            var masterAddresses = mKeyPairs.map(a => a.address);
            this.getMasterAddressWithMinimum(masterAddresses, amount).then(funds => {
                this.getAddressUtxo(funds.address).then(utxo => {
                    var transaction = new Bitcore.Transaction();
                    for(var i = 0; i < utxo.length; i++) {
                        transaction.from(utxo[i]);
                    }
                    transaction.to(destination, amount);
                    var change = helper.getMasterChangeAddress();
                    transaction.change(change.address);
                    for(var j = 0; j < mKeyPairs.length; j ++) {
                        if(mKeyPairs[j].address == funds.address) {
                            transaction.sign(mKeyPairs[j].secret);
                        }
                    }
                    var tx = {
                        account: account,
                        satoshis: (amount * -1),
                        timestamp: (new Date()).getTime(),
                        status: "transfer",
                        type: "transaction"
                    };
                    this.insert(tx).then(result => {
                        resolve(transaction);
                    }, error => reject(error));
                }, error => reject(error));
            }, error => reject(error));
        }, error => reject(error));
    });
}

我們假設我們的交換地址裝滿了瘋狂的比特幣以滿足需求。

第一步是確保我們的持有賬戶中有資金。我們可以執行總結每個交易的查詢以獲得有效數字。如果我們有足夠的,我們可以獲得所有10個主密鑰對和地址。我們需要檢查哪個地址有足夠的資金發送。請記住,這里的單一地址交易可能會有更多。

如果地址有足夠的資金,我們會獲得UTXO數據并開始進行交易。這次代替我們的錢包作為源地址,我們使用交換的錢包。在我們獲得簽名交易之后,我們想在數據庫中創建一個交易來減去我們正在傳輸的值。

在我們進入API端點之前,我想重新嘗試一些事情:

  • 我假設熱門的交易所有一個持有賬戶,以避免對錢包地址征收費用。

  • 我們在此示例中使用單地址交易,而不是聚合我們擁有的內容。

  • 我應該是在加密帳戶文檔中的關鍵數據。

  • 我沒有廣播任何交易,只創建它們。

現在讓我們關注我們的API端點,這是一個簡單的部分。

使用Express Framework設計RESTful API端點

請記住,正如我們在開始時配置的那樣,我們的端點將分為三個文件,這些文件充當分組。我們將從最小和最簡單的端點組開始,這些端點比其他任何端點都更實用。

打開項目的routes/utility.js文件并包含以下內容:

const Bitcore = require("bitcore-lib");
const Mnemonic = require("bitcore-mnemonic");

module.exports = (app) => {

    app.get("/mnemonic", (request, response) => {
        response.send({
            "mnemonic": (new Mnemonic(Mnemonic.Words.ENGLISH)).toString()
        });
    });

    app.get("/balance/value", (request, response) => {
        Request("https://api.coinmarketcap.com/v1/ticker/bitcoin/").then(market => {
            response.send({ "value": "$" + (JSON.parse(market)[0].price_usd * request.query.balance).toFixed(2) });
        }, error => {
            response.status(500).send(error);
        });
    });

}

這里我們有兩個端點,一個用于生成助記符種子,另一個用于獲取比特幣余額的法定值。這兩者都不是真正必要的,但是在第一次啟動時,生成種子值以便稍后保存在我們的配置文件中可能會很好。

現在打開項目的routes/account.js文件,以便我們處理帳戶信息:

const Request = require("request-promise");
const Joi = require("joi");
const helper = require("../app").helper;

module.exports = (app) => {

    app.post("/account", (request, response) => { });

    app.put("/account/address/:id", (request, response) => { });

    app.get("/account/addresses/:id", (request, response) => { });

    app.get("/addresses", (request, response) => { });

    app.get("/account/balance/:id", (request, response) => { });

    app.get("/address/balance/:id", (request, response) => { });

}

請注意,我們正在從尚未啟動的app.js文件中提取helper程序類。現在就跟它一起使用它以后會有意義,雖然它沒什么特別的。

在創建帳戶時,我們有以下內容:

app.post("/account", (request, response) => {
    var model = Joi.object().keys({
        firstname: Joi.string().required(),
        lastname: Joi.string().required(),
        type: Joi.string().forbidden().default("account")
    });
    Joi.validate(request.body, model, { stripUnknown: true }, (error, value) => {
        if(error) {
            return response.status(500).send(error);
        }
        helper.createAccount(value).then(result => {
            response.send(value);
        }, error => {
            response.status(500).send(error);
        });
    });
});

使用Joi我們可以驗證請求正文并在錯誤時拋出錯誤。假設請求正文是正確的,我們可以調用createAccount函數在數據庫中保存一個新帳戶。

創建帳戶后,我們可以添加一些地址:

app.put("/account/address/:id", (request, response) => {
    helper.addAddress(request.params.id).then(result => {
        response.send(result);
    }, error => {
        return response.status(500).send(error);
    });
});

使用發送的帳戶ID,我們可以調用我們的addAddress函數來對我們的文檔使用子文檔操作。

還不錯吧?

要獲取特定帳戶的所有地址,我們可能會有以下內容:

app.get("/account/addresses/:id", (request, response) => {
    helper.getAddresses(request.params.id).then(result => {
        response.send(result);
    }, error => {
        response.status(500).send(error);
    });
});

或者,如果我們不提供id,我們可以使用以下端點函數從所有帳戶獲取所有地址:

app.get("/addresses", (request, response) => {
    helper.getAddresses().then(result => {
        response.send(result);
    }, error => {
        response.status(500).send(error);
    });
});

現在可能是最棘手的端點功能。假設我們希望獲得帳戶余額,其中包括持有帳戶以及每個錢包地址。我們可以做到以下幾點:

app.get("/account/balance/:id", (request, response) => {
    helper.getAddresses(request.params.id).then(addresses => helper.getWalletBalance(addresses)).then(balance => {
        helper.getAccountBalance(request.params.id).then(result => {
            response.send({ "balance": balance.balance + result.balance });
        }, error => {
            response.status(500).send({ "code": error.code, "message": error.message });
        });
    }, error => {
        response.status(500).send({ "code": error.code, "message": error.message });
    });
});

以上將調用我們的兩個函數來獲得余額,并將結果加在一起以獲得一個巨大的余額。

帳戶端點不是特別有趣。創建交易更令人興奮。

打開項目的routes/transaction.js文件并包含以下內容:

const Request = require("request-promise");
const Joi = require("joi");
const Bitcore = require("bitcore-lib");
const helper = require("../app").helper;

module.exports = (app) => {

    app.post("/withdraw", (request, response) => { });

    app.post("/deposit", (request, response) => { });

    app.post("/transfer", (request, response) => { });

}

我們有三種不同類型的交易。我們可以為比特幣存入法定貨幣,為法定貨幣提取比特幣,并將比特幣轉賬到新的錢包地址。

我們來看看存款端點:

app.post("/deposit", (request, response) => {
    var model = Joi.object().keys({
        usd: Joi.number().required(),
        id: Joi.string().required()
    });
    Joi.validate(request.body, model, { stripUnknown: true }, (error, value) => {
        if(error) {
            return response.status(500).send(error);
        }
        Request("https://api.coinmarketcap.com/v1/ticker/bitcoin/").then(market => {
            var btc = value.usd / JSON.parse(market)[0].price_usd;
            var transaction = {
                account: value.id,
                usd: value.usd,
                satoshis: Bitcore.Unit.fromBTC(btc).toSatoshis(),
                timestamp: (new Date()).getTime(),
                status: "deposit",
                type: "transaction"
            };
            helper.insert(transaction).then(result => {
                response.send(result);
            }, error => {
                response.status(500).send(error);
            });
        }, error => {
            response.status(500).send(error);
        });
    });
});

在我們驗證輸入后,我們使用CoinMarketCap檢查美元比特幣的當前值。使用響應中的數據,我們可以根據存入的美元金額計算出應該獲得多少比特幣。

創建數據庫交易后,我們可以保存它,因為它是一個正數,它將在查詢時返回正余額。

現在讓我們說我們想從比特幣中提取資金:

app.post("/withdraw", (request, response) => {
    var model = Joi.object().keys({
        satoshis: Joi.number().required(),
        id: Joi.string().required()
    });
    Joi.validate(request.body, model, { stripUnknown: true }, (error, value) => {
        if(error) {
            return response.status(500).send(error);
        }
        helper.getAccountBalance(value.id).then(result => {
            if(result.balance == null || (result.balance - value.satoshis) < 0) {
                return response.status(500).send({ "message": "There are not `" + value.satoshis + "` satoshis available for withdrawal" });
            }
            Request("https://api.coinmarketcap.com/v1/ticker/bitcoin/").then(market => {
                var usd = (Bitcore.Unit.fromSatoshis(value.satoshis).toBTC() * JSON.parse(market)[0].price_usd).toFixed(2);
                var transaction = {
                    account: value.id,
                    satoshis: (value.satoshis * -1),
                    usd: parseFloat(usd),
                    timestamp: (new Date()).getTime(),
                    status: "withdrawal",
                    type: "transaction"
                };
                helper.insert(transaction).then(result => {
                    response.send(result);
                }, error => {
                    response.status(500).send(error);
                });
            }, error => {
                response.status(500).send(error);
            });
        }, error => {
            return response.status(500).send(error);
        });
    });
});

類似的事件正在這里發生。在驗證請求主體后,我們獲得帳戶余額并確保我們提取的金額小于或等于我們的余額。如果是,我們可以根據CoinMarketCap的當前價格進行另一次交易。我們將使用負值創建一個交易并將其保存到數據庫中。

在這兩種情況下,我們都依賴于CoinMarketCap,它在過去一直存在負面爭議。你可能希望為交易選擇不同的資源。

最后,我們有轉賬:

app.post("/transfer", (request, response) => {
    var model = Joi.object().keys({
        amount: Joi.number().required(),
        sourceaddress: Joi.string().optional(),
        destinationaddress: Joi.string().required(),
        id: Joi.string().required()
    });
    Joi.validate(request.body, model, { stripUnknown: true }, (error, value) => {
        if(error) {
            return response.status(500).send(error);
        }
        if(value.sourceaddress) {
            helper.createTransactionFromAccount(value.id, value.sourceaddress, value.destinationaddress, value.amount).then(result => {
                response.send(result);
            }, error => {
                response.status(500).send(error);
            });
        } else {
            helper.createTransactionFromMaster(value.id, value.destinationaddress, value.amount).then(result => {
                response.send(result);
            }, error => {
                response.status(500).send(error);
            });
        }
    });
});

如果請求包含源地址,我們將從我們自己的錢包轉賬,否則我們將從交換管理的錢包轉賬。

所有這些都基于我們之前創建的功能。

通過端點,我們可以專注于引導我們的應用程序并得出結論。

引導Express Framework應用程序

現在我們有兩個文件保持不受示例的影響。我們還沒有添加配置或驅動邏輯來引導我們的端點。

打開項目的config.json文件,并包含以下內容:

{
    "mnemonic": "manage inspire agent october potato thought hospital trim shoulder round tired kangaroo",
    "host": "localhost",
    "bucket": "bitbase",
    "username": "bitbase",
    "password": "123456"
}

記住這個文件非常敏感。考慮將其鎖定或甚至使用不同的方法。如果種子被暴露,則可以毫不費力地獲得所有用戶帳戶和交換帳戶的每個私鑰。

現在打開項目的app.js文件并包含以下內容:

const Express = require("express");
const BodyParser = require("body-parser");
const Bitcore = require("bitcore-lib");
const Mnemonic = require("bitcore-mnemonic");
const Config = require("./config");
const Helper = require("./classes/helper");

var app = Express();

app.use(BodyParser.json());
app.use(BodyParser.urlencoded({ extended: true }));

var mnemonic = new Mnemonic(Config.mnemonic);
var master = new Bitcore.HDPrivateKey(mnemonic.toHDPrivateKey());

module.exports.helper = new Helper(Config.host, Config.bucket, Config.username, Config.password, master);

require("./routes/account.js")(app);
require("./routes/transaction.js")(app);
require("./routes/utility.js")(app);

var server = app.listen(3000, () => {
    console.log("Listening at :" + server.address().port + "...");
});

我們正在做的是初始化Express,加載配置信息以及鏈接我們的路由。module.exports.helper變量是我們的單例,將在每個其他JavaScript文件中使用。

到此,關于“怎么用Node.js和NoSQL開發加密貨幣應用程序”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

钦州市| 云和县| 宜阳县| 建昌县| 宁化县| 永定县| 垦利县| 安龙县| 墨脱县| 水城县| 启东市| 宁城县| 锡林郭勒盟| 民县| 台北市| 名山县| 合阳县| 柳江县| 凤庆县| 兴海县| 壤塘县| 富平县| 闽侯县| 砚山县| 金堂县| 南投县| 宁河县| 鹰潭市| 来安县| 韶关市| 静宁县| 兰坪| 延长县| 礼泉县| 个旧市| 英山县| 萨迦县| 田阳县| 招远市| 酉阳| 镇远县|