一、安裝錢包
請參考另一篇隨筆: 入口
二、獲取測試usdt(TestOmni)步驟:
1、導入地址到錢包,往該地址充值測試比特幣,
2、然后往 moneyqMan7uh8FqdCA2BV5yZ8qVrc9ikLP 地址發送部分btc(testnet),即可返還部分usdt(TestOmni)
3、omni_getbalance 方法查看到賬情況 或者訪問測試網絡瀏覽器查詢
介紹一些常用的RPC接口命令:
查看地址私鑰
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword dumpprivkey n1dnFGMxuxkDf1Ns5G2uYhaqk2ETWPuYQG(btc/usdt地址)
查看到賬:
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword getbalance
獲取交易信息:
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword omni_listtransactions
查看入賬:
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword omni_getbalance mhf2ibPWMoeyibR2jS3jPLZQYTJsFSoG5r 1 (1: 表示彩色幣id,usdt為31,錢包客戶端我選擇的是2)
測試網絡進入QT桌面端
> ./bin/omnicore-qt -testnet -server -rpcbind=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword
獲取指定地址交易列表listUnspent
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword listunspent 0 999999 '["mhf2ibPWMoeyibR2jS3jPLZQYTJsFSoG5r"]'
發送usdt
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword omni_sendrawtx "mhf2ibPWMoeyibR2jS3jPLZQYTJsFSoG5r" "000000000000001f000000000000000a" "msis3b45PQriomes1zCAfNJpobggP1yusr"
導入特定地址到節點:
> ./bin/omnicore-cli -rpcconnect=127.0.0.1 -rpcport=18332 -rpcuser=RPCUser -rpcpassword=RPCPassword importprivkey cVKMjDVaWevxmRCrNXjTPpz77SSjWvQWp1eCj5zKBpEcaASK7Gib '' false
'cVKMjDVaWevxmRCrNXjTPpz77SSjWvQWp1eCj5zKBpEcaASK7Gib': 地址賬戶
false:表示是否全節點掃描
如果(btc/usdt)要通過api查詢余額,rescan需要設置為true
共享一個地址:
usdt測試網絡地址(有測試幣):n1dnFGMxuxkDf1Ns5G2uYhaqk2ETWPuYQG
私鑰:cVZT8qHGs5g1qyVYmFgfUyz7CcRS7LX84xjgdNS8DdRbtJ5uXtYU
三、開發
這里主要介紹利用nodejs生成USDT地址,新建USDT轉賬交易等;
1、環境安裝
(1)、8.x 以上版本nodejs、mongodb
(2)、express、pm2
2、依賴包 | btc官方提供的庫和加密包等 | usdt基於btc底層協議,所以很多api可以共用
(1)、randomstring
(2)、bitcoinjs-lib
(3)、bigi
(4)、crypto
3、部分模型准備
(1) 地址表
id: { type: String, required: true },
address: { type: String, required: true, default: '' }, //USDT地址
testnet: { type: Boolean, required: true, default: true }, //是否為測試網絡地址
privateKey: { type: String, required: true, default: '' }, //USDT地址私鑰
privateKeySalt: { type: String, required: true, default: '' }, //USDT地址加密鹽
hash: { type: String, required: true, default: '' }, //防篡改hash
used: { type: Boolean, required: true, default: true }, //是否已被使用
watch: { type: Boolean, required: true, default: false }, //是否已經添加到bitcoind監控列表
invalid: { type: Boolean, required: true, default: false }, //是否已經失效
(2) 交易表
id: { type: String, required: true },
txid: { type: String, required: true }, // 交易編號
fee: { type: Number }, // 手續費
sendingaddress: { type: String, required: true, default: '' }, // 發送方
referenceaddress: { type: String, required: true, default: '' }, // 接收方
ismine: { type: Boolean }, // 訂單是否涉及錢包中的地址
version: { type: Number }, // 版本
type_int: { type: Number }, // 交易類型為數字
type: { type: String, default: '' }, // 交易類型為字符串
propertyid: { type: Number, required: true }, //要發送的令牌的標識符 如 31對應的是usdt
divisible: { type: Boolean }, //令牌是否可以分割
amount: { type: Number, required: true }, // 充值數量
valid: { type: Boolean }, // 交易是否有效
blockhash: { type: String }, // 相應塊的hash
blocktime: { type: Number }, // 最后處理的塊的時間戳
positioninblock: { type: Number }, // 塊內交易的位置
block: { type: Number }, // 當前塊高度
confirmations: { type: Number, default: 0 }, // 當前確認數
3、部分代碼塊
(1)、生成usdt錢包地址
function createAddress(){
try {
let string = random.randomString(1048) //創建隨機值
let hash = bitcoin.crypto.sha256(string) //sha256加密,創建對應哈希
let d = bigi.fromBuffer(hash)
let keyPair = new bitcoin.ECPair(d, null, { network: network }) //創建新私鑰
let privateKey = keyPair.toWIF()
let publicAddress = keyPair.getAddress()
let obj = {
id: unique.uuid(),
address: publicAddress,
testnet: appConfig.usdt.testnet,
privateKey: privateKey,
}
let addr = new Address(obj)
addr.encryptPrivateKey() //私鑰加密
addr.createHash() //指定鹽加密
importAddrToNet(publicAddress).then(function(data) { // 添加到對應網絡節點
return addr.save() //保存地址到數據庫
}).then(function(d) {
return res.json({
data: {
address: publicAddress //最后返回地址
}
})
}).catch(function(e) {
ws.log('importAddrToNet error', e)
})
} catch (e) {
ws.error(`catch importAddrToNet error ${e}`)
}
}
(2)、生成交易
usdt作為btc的一種彩色幣,他的每次交易的原理,其實是生成btc交易,把usdt交易相關粘附在該筆交易上
所以usdt轉賬需要提供少額的btc作為手續費, 一般是需要提供專門手續費地址賬號。
* @param {*} id omni_id usdt:31
* @param {*} sender_address 轉出金額的臨時地址
* @param {*} sender_privatekey 轉出臨時地址的私鑰
* @param {*} value 轉賬金額
* @param {*} receiver_address 接收地址
* @param {*} fee 手續費
const createTransaction = (sender_address, value, id) => {
try {
isBalanceEnough(sender_address, value, id).then(e => { //驗證發送方余額
if (e) {
return listUnspentForFee(sender_address, fee) //獲取手續費地址賬號的未花費交易unspentList
} else {
ws.log('余額不足')
return reject(`余額不足,${e}`)
}
}).then(async (sender_tx) => {
if (!tx.length) {
ws.log('等待上筆交易確認后再嘗試..')
return resolve('等待上筆交易確認后再嘗試..')
}
const _payload = await omniHelper.createpayloadSimplesend(id, parseFloat(value).toString()) //創建Usdt交易
await omniHelper.createRawtransaction(sender_tx, {}) // 創建交易
const opreturn = await omniHelper.createRawtx_opreturn(create, _payload) // //usdt交易附加到BTC交易上
const reference = await omniHelper.createRawtx_reference(opreturn, receiver_address) //設置歸總地址
const data = await omniHelper.createRawtx_change(reference, sender_tx, sender_address, fee) //填寫手續費及找零地址
const sign = await omniHelper.signRawtransaction(data, sender_tx, [sender_privatekey]) //獲取原生交易hex
const result = await omniHelper.sendRawtransaction(sign.hex) //廣播交易
return await isOnOmni(result) //驗證結果
}).then(data => {
resolve(data)
}).catch(e => {
reject(e)
})
} catch (error) {
ws.error(error)
}
}
總結
本篇隨筆主要提供一種方案;
退圈已久,需要探討的可以留言或者私信,希望這些總結可以給到你們幫助;