HTTPS上でAPIを叩く。

ブツ

画像

トランザクション情報を作成する。HTMLのinput要素値からcreate_sendへ引数を渡して実行結果のJSONを表示する。

送金はされないので好きなように試せる。

実行

NAME='Html.mpchain.SreateSned.20221002110114'
git clone https://github.com/ytyaru/$NAME
cd $NAME/docs
./server.sh

コード

ファイル 概要
main.js メイン
throttle.js 指定したメソッドを指定時間内で1回だけ実行するためのクラス
mpchain.js mpchain APIcreate_sendを実行するクラス

mpchain APIcounterParty APIcreate_sendを呼び出す

JavaScriptのfetchでHTTPSリクエストする。

const res = await fetch(URL, options)

mpchain APIcounterParty APIを叩くには次のエントリポイントとなる。cbという名前からしてcounterBlock APIにみえるが、パラメータの設定によりcounterParty APIを叩くように設定できる。(後述)

const URL = `https://mpchain.info/api/cb/`

HTTPメソッドはPOST。HTTPヘッダは以下のとおり。

const METHOD = (isPost) ? 'POST' : 'GET'
const HEADERS = { 'Content-Type': 'application/json' }

POSTするJSONを作成する。counterParty APIを叩くようにするにはmethod"proxy_to_counterpartyd"を渡す。呼び出したいAPI名create_sendparams.methodのほうにセットする。そのAPIに渡す引数はparams.paramsにセットする。つまりcounterParty APIのときはparams: {method: "create_send", params: {...}}のようにparamsが二階層になる。

return {
    id: 0,
    jsonrpc: "2.0",
    method: (isParty) ? "proxy_to_counterpartyd" : method,
    params: (isParty) ? {method: method, params: params} : params,
}

create_sendに渡す引数は以下。

const params = {
    source: from,
    destination: to,
    asset: "MONA",
    quantity: parseInt(quantity),
    memo: null,
    memo_is_hex: "no",
    fee_per_kb: parseInt(feePerKb * 1000),
    allow_unconfirmed_inputs: true,
    extended_tx_info: true,
    disable_utxo_locks: disableUtxoLocks,
}

以上。

もしcounterParty APIでなくcounterBlock APIなら、呼び出したいAPI名はmethodにセットする。paramsはシンプルに一層だけでその中にmethodparamsは不要。直にそのAPIのパラメータを書けばいい。

全コードは以下。

mpchain.js

class Mpchain {
    static async createSend(from, to, quantity, feePerKb, disableUtxoLocks=true) {
        const params = {
            source: from,
            destination: to,
            asset: "MONA",
            quantity: parseInt(quantity),
            memo: null,
            memo_is_hex: "no",
            fee_per_kb: parseInt(feePerKb * 1000),
            allow_unconfirmed_inputs: true,
            extended_tx_info: true,
            disable_utxo_locks: disableUtxoLocks,
        }
        return await this.#request(this.#makeParams('create_send', params))
    }
    static #makeParams(method, params, isParty=true) { // method:str, params:obj, isParty:bool(true:counterParty, false:counterBlock)
        return {
            id: 0,
            jsonrpc: "2.0",
            method: (isParty) ? "proxy_to_counterpartyd" : method,
            params: (isParty) ? {method: method, params: params} : params,
        }
    }
    static async #request(data, isPost=true) {
        console.log(data)
        const URL = `https://mpchain.info/api/cb/`
        const METHOD = (isPost) ? 'POST' : 'GET'
        const HEADERS = { 'Content-Type': 'application/json' }
        const options = { method: METHOD, headers: HEADERS }
        if (isPost) { options.body = JSON.stringify(data) }
        const res = await fetch(URL, options)
        return await res.json()
    }
}

index.html

<input id="from" value="MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu">
<input id="to" value="MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu">
<input id="quantity" type="number" min="0" value="11411400">
<input id="fee-per-kb" type="number" min="0" max="200" value="10">
<textarea id="result"></textarea>

UI。create_sendするときの引数を受け付ける。

id 説明
from 支払モナコイン用アドレス
to 受取モナコイン用アドレス
quantity 支払額
fee-per-kb 手数料

なお、支払額と手数料は1以上の整数値で指定する(値 * 10⁻⁸ MONA)。1 = 0.00000001 MONA

main.js

window.addEventListener('DOMContentLoaded', async(event) => {
    const throttle = new Throttle()
    const ids = ['from', 'to', 'quantity', 'fee-per-kb']
    for (const id of ids) { 
        document.getElementById(id).addEventListener('input', async(event) => {
            createSend({ id: event.target.id, value: event.target.value })
        })
    }
    function createSend(d=null) {
        const values = ids.map(id=>document.getElementById(id).value)
        if (d) { values[ids.find(id=>id === d.id)] = d.value }
        throttle.run(async()=>{
            document.querySelector(`#result`).value = JSON.stringify(
                await Mpchain.createSend(...values))
        })
    }
    createSend()
});

DRYに書けるよう工夫した。

from, to, quantity, fee-per-kbの各要素はそれぞれ値が入力されたときにcreate_sendを実行する。このイベント実装のコードはほぼ同じである。ちがう部分はidvalueだけなので、それをキーにして同じコードで書けるようにした。

もし共通化しないと以下のように類似コードまみれになってウザい。

document.querySelector(`#from`).addEventListener('input', async(event) => {
    createSend(
        event.target.value,
        document.querySelector(`#to`).value,
        parseInt(document.querySelector(`#quantity`).value),
        parseInt(document.querySelector(`#fee-per-kb`).value))
})
document.querySelector(`#to`).addEventListener('input', async(event) => {
    createSend(
        document.querySelector(`#from`).value,
        event.target.value,
        parseInt(document.querySelector(`#quantity`).value),
        parseInt(document.querySelector(`#fee-per-kb`).value))
})
document.querySelector(`#quantity`).addEventListener('input', async(event) => {
    createSend(
        document.querySelector(`#from`).value,
        document.querySelector(`#to`).value,
        parseInt(event.target.value),
        parseInt(document.querySelector(`#fee-per-kb`).value))
})
document.querySelector(`#fee-per-kb`).addEventListener('input', async(event) => {
    createSend(
        document.querySelector(`#from`).value,
        document.querySelector(`#to`).value,
        parseInt(document.querySelector(`#quantity`).value),
        parseInt(event.target.value))
})
createSend(
    document.querySelector(`#from`).value,
    document.querySelector(`#to`).value,
    parseInt(document.querySelector(`#quantity`).value),
    parseInt(document.querySelector(`#fee-per-kb`).value))