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 APIでcreate_sendを実行するクラス |
mpchain APIでcounterParty APIのcreate_sendを呼び出す
JavaScriptのfetchでHTTPSリクエストする。
const res = await fetch(URL, options)
mpchain APIのcounterParty 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_send
はparams.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
はシンプルに一層だけでその中にmethod
やparams
は不要。直にその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を実行する。このイベント実装のコードはほぼ同じである。ちがう部分はid
とvalue
だけなので、それをキーにして同じコードで書けるようにした。
もし共通化しないと以下のように類似コードまみれになってウザい。
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))