Omni-usdt離線交易

關於omni-usdt離線交易:

如果是正式鏈,可以通過下面這個api獲取utxo:
blockchain : https://blockchain.info/unspent?active=你需要用到的地址

拿到未使用的utxo就可以進行離線交易了。
添加的依賴:

<dependency>
	<groupId>org.bitcoinj</groupId>
	<artifactId>bitcoinj-tools</artifactId>
	<version>0.14.7</version>
</dependency>
<dependency>
	<groupId>org.bitcoinj</groupId>
	<artifactId>bitcoinj-examples</artifactId>
	<version>0.14.7</version>
</dependency>
<dependency>
	<groupId>org.bitcoinj</groupId>
	<artifactId>bitcoinj-core</artifactId>
	<version>0.14.7</version>
</dependency>

構建一個實體類:

@Data
public class UnSpentUtxo implements Serializable {
    private static final long serialVersionUID = -7417428486644921613L;

    private String hash; //未交易hash
    private long txN;//vout
    private long value;//金額
    private int height; //高度
    private String script;//簽名
    private String address;//錢包地址
    }

調用方法:

 /**
     *
     * @param ptivateKey btc私鑰
     * @param fromAddress 轉出地址
     * @param privateUsdtKey usdt密鑰
     * @param recivAddress  usdt接收地址
     * @param fee   手續費
     * @param omniHex   usdthex
     * @param unBtcUtxo btc utxo  --手續費用
     * @param unSpentUsdtUtxo usdt utxo --轉賬用
     * @return
     */
    public String CreateRawTransaction(String ptivateKey,String fromAddress,String privateUsdtKey,String recivAddress,long fee,String omniHex,
                                       List<UnSpentUtxo> unBtcUtxo,List<UnSpentUtxo> unSpentUsdtUtxo){
        List<UTXO> btcUtxos = new ArrayList<>();
        List<UTXO> usdtUtxos = new ArrayList<>();
        try {


            if(!unBtcUtxo.isEmpty() && !unSpentUsdtUtxo.isEmpty()){
                //find a btc eckey info
                DumpedPrivateKey btcPrikey = DumpedPrivateKey.fromBase58(TestNet3Params.get(), ptivateKey);
                ECKey btcKey = btcPrikey.getKey();

                //find a usdt eckey info
                DumpedPrivateKey usdtPrivateKey = DumpedPrivateKey.fromBase58(TestNet3Params.get(), privateUsdtKey);
                ECKey usdtKey = usdtPrivateKey.getKey();


                //rec 地址
                Address receiveAddress = Address.fromBase58(TestNet3Params.get(),recivAddress);

                //create a transaction
                Transaction tx = new Transaction(TestNet3Params.get());

                //odd Address;
                Address oddAddress = Address.fromBase58(TestNet3Params.get(), fromAddress);

                //如果需要找零  消費列表總額-已經轉賬的金額 -手續費
                long valueBtc = unBtcUtxo.stream().mapToLong(UnSpentUtxo::getValue).sum();
                long valueUSDT = unSpentUsdtUtxo.stream().mapToLong(UnSpentUtxo::getValue).sum();
                //總輸入 - 手續費 - 546 - 546 = 找零金額
                long leave = (valueBtc + valueUSDT) - fee - 1092;
                if(leave > 0){
                    tx.addOutput(Coin.valueOf(leave),oddAddress);
                }

                //usdt transaction
                tx.addOutput(Coin.valueOf(546),new Script(Utils.HEX.decode(omniHex)));
                //send to address
                tx.addOutput(Coin.valueOf(546),receiveAddress);

                //btc utxos is an array of inputs from my wallet
                for(UnSpentUtxo unUtxo : unBtcUtxo){
                    btcUtxos.add(new UTXO(Sha256Hash.wrap(unUtxo.getHash()),
                            unUtxo.getTxN(),
                            Coin.valueOf(unUtxo.getValue()),
                            unUtxo.getHeight(),
                            false,
                            new Script(Utils.HEX.decode(unUtxo.getScript())),
                            unUtxo.getAddress()));
                }

                //usdt utxos is an array of inputs from my wallet
                for(UnSpentUtxo unUtxo: unSpentUsdtUtxo){
                    usdtUtxos.add(new UTXO(Sha256Hash.wrap(unUtxo.getHash()),
                            unUtxo.getTxN(),
                            Coin.valueOf(unUtxo.getValue()),
                            unUtxo.getHeight(),
                            false,
                            new Script(Utils.HEX.decode(unUtxo.getScript())),
                            unUtxo.getAddress()));
                }

                //create usdt utxo data
                for(UTXO utxo : usdtUtxos){
                    TransactionOutPoint outPoint = new TransactionOutPoint(TestNet3Params.get(), utxo.getIndex(), utxo.getHash());
                    tx.addSignedInput(outPoint, utxo.getScript(),usdtKey,Transaction.SigHash.ALL,true);
                }

                //create btc utxo data
                for(UTXO utxo : btcUtxos){
                    TransactionOutPoint outPoint = new TransactionOutPoint(TestNet3Params.get(), utxo.getIndex(), utxo.getHash());
                    tx.addSignedInput(outPoint, utxo.getScript(),btcKey,Transaction.SigHash.ALL,true);
                }

                Context context = new Context(TestNet3Params.get());
                tx.getConfidence().setSource(TransactionConfidence.Source.NETWORK);

                tx.setPurpose(Transaction.Purpose.USER_PAYMENT);

                log.info("===============[USDT sign success,hash is {}==========", tx.getHashAsString());
                return new String(Hex.encodeHex(tx.bitcoinSerialize()));
            }}catch (Exception e){
            log.info("========com.bscoin.coldwallet.cointype.usdt.RawTransaction.createRawTransaction(String, String, String, String, String, long, String, List<UnSpentUtxo>, List<UnSpentUtxo>):{}  ==="
                    ,e.getMessage(),e);
        }
        return null;
    }

調用:

public static void main(String[] args) {
        String mkPrivateKey = "";
        String usdtPri = "";
        
        //構造Data前綴
        String methodStrart = "6a146f6d6e69";
        //幣種唯一標識的16進制---這個是1,我用測試鏈的omni代幣
        String coinProperity1 = "0000000000000001";
        //幣種唯一標識的16進制---這是31,usdt。
        String coinProperity31 = "000000000000001f";

        //構造Data的數量16進制數。  需要 基本數量 *10^8再轉,我轉的數量爲5個
        String Hex16ToBalance = "000000001dcd6500";

        //構造的Data 爲方法前綴+幣唯一標識16進制+轉賬數量的16進制
        String omniHex = methodStrart+coinProperity1+Hex16ToBalance;


        Map m = new HashMap();
        List<UnSpentUtxo> us = new ArrayList<UnSpentUtxo>();
        //第一個utxo爲手續費用到的
        UnSpentUtxo u = new UnSpentUtxo();
        u.setAddress("mkUWwGMQ2nHbRPyRL2czV9HnFGqg6XMqUL");//地址
        u.setHash("af2ec076ae16a0e0ea1aac82af35817b8b2ba81edc5a4f7f77597de7a623ece8");//交易hash
        u.setHeight(1696973);//確認交易的區塊高度
        u.setScript("76a9143662a0fc506262a3c658b46df05183b19b64f8e688ac");//script
        u.setTxN(0);//utxo中的vout
        u.setValue(1900000);//數量--如果用listunspent的話,需要*10^8
        us.add(u);

        //第二個爲載體(真正需要轉出去用到的)
        List<UnSpentUtxo> us2 = new ArrayList<UnSpentUtxo>();
        UnSpentUtxo u3 = new UnSpentUtxo();
        u3.setAddress("msCzB99PdAZRfeaFSkrNZjfqBgavWU2Kjs");
        u3.setHash("7e3d4fed3c849960758c505b56cf967b6c3b36b6aedbfa39c39b8b3690415732");
        u3.setHeight(1612275);
        u3.setScript("76a914803b979506bf04579b2a24d3c5fd01895272fac488ac");
        u3.setTxN(2);
        u3.setValue(546);

        us2.add(u3);


        m.put("btcUtxo", us);
        m.put("usdtUtxo", us2);
        m.put("omniHex", methodStrart+coinProperity1+Hex16ToBalance);

        System.out.println("傳輸參數:" + JSONObject.toJSONString(m));

        /**
         * 第一個,手續費的私鑰
         * 第二個,手續費地址
         * 第三個:要付款的usdt私鑰--(付款了5個數量爲16進制,需要5*10^8 再轉16)
         * 第四個:接收地址
         * 第五個:手續費費用 需要/10^8纔是真實,例如下面的就是0.0001個btc手續費
         * 第五個,構造的data,--爲 固定前綴6a146f6d6e69 + 幣種唯一標識的十六進制 + 轉賬數量 * 10^8 再轉16進制
         * 第六個,手續費utxo
         * 第七個,轉賬的0.00000546 utxo
         *
         * 調用了之後,會生成已經簽好名的交易,
         * 通過廣播sendrawtransaction接口返回生成的hashId。
         *
         * 消耗了手續費的utxo、轉賬的utxo
         * 接收地址會收到一個新的0.00000546UTXO,
         * 手續費會返回一個新的utxo
         */
        String c = new UnSpentUtxo().CreateRawTransaction(mkPrivateKey, "mkUWwGMQ2nHbRPyRL2czV9HnFGqg6XMqUL",usdtPri,
                "mkUWwGMQ2nHbRPyRL2czV9HnFGqg6XMqUL",10000,omniHex,us,us2);//手續費是0.0001BTC
        System.out.println(c);


        try {
            String txid = rpcUtils.invoke("http://127.0.0.1:8888", "sendrawtransaction","c3czZGY6d2Vyc3ZzZGY=" , new Object[]{c});
            System.out.println(txid);
        } catch (Exception e) {
            log.error("調用失敗:{}", e.getMessage());
        }
    }

調用結果:

傳輸參數:{"omniHex":"6a146f6d6e690000000000000001000000001dcd6500","usdtUtxo":[{"address":"msCzB99PdAZRfeaFSkrNZjfqBgavWU2Kjs","hash":"7e3d4fed3c849960758c505b56cf967b6c3b36b6aedbfa39c39b8b3690415732","height":1612275,"script":"76a914803b979506bf04579b2a24d3c5fd01895272fac488ac","txN":2,"value":546}],"btcUtxo":[{"address":"mkUWwGMQ2nHbRPyRL2czV9HnFGqg6XMqUL","hash":"af2ec076ae16a0e0ea1aac82af35817b8b2ba81edc5a4f7f77597de7a623ece8","height":1696973,"script":"76a9143662a0fc506262a3c658b46df05183b19b64f8e688ac","txN":0,"value":1900000}]}
四月 15, 2020 9:57:31 上午 org.bitcoin.Secp256k1Context <clinit>
信息: java.lang.UnsatisfiedLinkError: no secp256k1 in java.library.path
四月 15, 2020 9:57:31 上午 org.bitcoinj.core.Context <init>
信息: Creating bitcoinj 0.14.7 context.
四月 15, 2020 9:57:31 上午 com.hlgj.entity.UnSpentUtxo CreateRawTransaction
信息: ===============[USDT sign success,hash is 2549a0c2d058e4f262db57ce498b6fa42e46bc3014420808053fe0bd0b77e9e3==========
010000000232574190368b9bc339fadbaeb6363b6c7b96cf565b508c756099843ced4f3d7e020000006b483045022100f76ab6398dcf01a118c22ff1f9cfc254e0eb7a4f355a0be96835a90b1b0640d7022042f5eff1026fa8ffa58c07084565893fb2844e2fb03466bdb05f8e74673d78308121031b6c481878b001ee6971bc494dbed93f88120844050d81e79481c71576840f39ffffffffe8ec23a6e77d59777f4f5adc1ea82b8b7b8135af82ac1aeae0a016ae76c02eaf000000006a47304402201ed328cdb85468ec850ebff23c9074eef37249a8f91d7bd8778c509648c3855e02202cd74327ea177c3338929e1c0fbc8572ef89ad905881e91a2513fe4581837b96812103de8addf3269ab5a9cfe55e1ba9c7e395dec92a04853f1c5c43a815ae20c4f7e0ffffffff03aed41c00000000001976a9143662a0fc506262a3c658b46df05183b19b64f8e688ac2202000000000000166a146f6d6e690000000000000001000000001dcd650022020000000000001976a9143662a0fc506262a3c658b46df05183b19b64f8e688ac00000000//已經簽名的交易
2549a0c2d058e4f262db57ce498b6fa42e46bc3014420808053fe0bd0b77e9e3//這個是調用之後返回的hash

調用了之後, 會發現:
omni錢包,少掉了兩個utxo,
就是上述填入的u 還有 us3.
但同時手續費地址會收到一筆新的utxo(找零返回的),接收地址也多了一筆0.00000546的utxo:

 {
    "txid": "2549a0c2d058e4f262db57ce498b6fa42e46bc3014420808053fe0bd0b77e9e3",
    "vout": 0,
    "address": "mkUWwGMQ2nHbRPyRL2czV9HnFGqg6XMqUL",
    "label": "watch-only test",
    "scriptPubKey": "xxxxxxxx",
    "amount": 0.01889454,
    "confirmations": 56,
    "spendable": false,
    "solvable": false,
    "safe": true
  }這筆是找零返回的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章