Arweave Client
The goar client implements all Arweave HTTP API . Developers can use the goar client to call these APIs to obtain the basic information of Arweave network and Arweave transaction information conveniently.
Usage
Install
go get github.com/everFinance/goar
Create Goar Client
package main
import (
"github.com/everFinance/goar"
"time"
)
func main() {
arUrl := "https://arweave.net"
cli := goar.NewClient(arUrl)
}
Note:
arUrl
: Address of Arweave gateway or Arweave Node, All the relevant information of Arweave network can be obtained by calling the APIs of the gateway or node. In this example, we fill in the gateway address officially provided by Arweave.cli
: Client instance, you can get various information of Arweave network by calling the method of this instance.- When we introduce the methods in client next, we have created an instance of cli by default.
Get Arweave Network Information
info, err := cli.GetInfo()
if err != nil {
panic(err)
}
fmt.Println(info)
return:
{
"network": "arweave.N.1",
"version": 5,
"release": 52,
"height": 1003310,
"current": "WurQMcQD_f_YPDHi8fP7ClNebdLJTMCqU_50msl1jO47zVblGKfFjL5gazw-Tgu2",
"blocks": 1003311,
"peers": 25545,
"queue_length": 0,
"node_state_latency": 0
}
This method returns the basic information of Arweave network. Including version, block height, number of nodes, etc.
Get All Peers
peers, err := cli.GetPeers()
if err != nil {
panic(err)
}
fmt.Println(peers)
return:
[
"198.54.132.54:55252",
"223.204.22.110:1984",
"207.53.233.64:1984",
"131.239.134.6:1984",
...............,
"176.9.24.56:1984",
"161.35.15.191:1984",
"157.230.2.154:1984",
"5.9.18.85:1984",
]
This method will return the current Arweave nodes info,present in ip:protNum
form.
Get Meta Info of Transaction
arId := "sUfG7jvu7PBQptlSIxtl6t5zD9LBMxv66_uVAlBk8dU"
tx, err := cli.GetTransactionByID(arId)
if err != nil {
panic(err)
}
fmt.Println(tx)
return:
{
"format": 2,
"id": "sUfG7jvu7PBQptlSIxtl6t5zD9LBMxv66_uVAlBk8dU",
"last_tx": "qs7DSGzs55TDuu2J3rLjH2zv0CxikbWO8Cv6CopOoNUfskQ3vvwmu2muyBjAx-Gi",
"owner": "ybuxOeQh6PUQnz1t8h4-sZ1WMLWbq2r8xLaRgAofKimabNKUFW37UpaNXpLu-NCoPutYksFbh46RutWB3mxZaBFRwaWPHHg9qsvqUMrnQjmIAUom_Mkhewp-0o3SXl0PhaIlwLuUzJpQYBe2alZtnDSWLfEp6BP7is5th6KNeEq7_xGEPMSyxP6y6emEiYGAqpcnueM0NdDBcyjUmlmOrU4z-NHL_hBrSWvtD5hcuuaLvZPH9UCocWXyBBZ1gNnGsGEYBFu2bF_R6Ex3g_iY0MmdT0E52MldtkiiUQ9gFSffyUgf_WLyFDKtEkvytP2nqmyPuhouK2vehAcSsWVEdrw4469ccB-iiY4T5ACTRW9xnPGSiefcHjdS7DdnAxxL9PBl0dZPoJDR203Jwvamk7ekdquXBoVCvoxkER1bro7z5MHP9tRxT5VY_oqi9_O1cUGvZQ9gSlUedlsxbDClKhKpsGvJvOA8ecCuZszZLFJKpqkmkcHzJdlqcneVd4Kcnszb2Fw621r61VU8cXyF3mhk_7tRpmJM75wzSissCBq08eBaLeOhzYiNlA0rJFOBNT6uRASbPaPpF7WfvA5gRcHinPEdOdKXeQtS58-Z8TkD_kYYsL2G7-2pjeh1q9gdaCeff0OHwsLstFHTxgtjrZgi5PWk35_4sdEQalzTwYs",
"tags": [
{
"name": "Q29udGVudC1UeXBl",
"value": "aW1hZ2UvcG5n"
}
],
"target": "",
"quantity": "0",
"data": "",
"data_size": "324218",
"data_tree": [],
"data_root": "vwuJoWSU5UFmarPmtWNfXk8ccsb92LMfy8bHpSAjXIc",
"reward": "106343596",
"signature": "W1FIZlGnAHm3-gfEf7a3fNfI_MORpvqn6VpLn37A-TCGV98p5HlQ8BI7lLBpLkBaO7Pd6ol3k_ZCW36-FPREJtBAGiQsv9CZRDmR6ABKqR1Ib1vJF7qFTNAc3XNWfO03xdVvuQWgi9Vsjtrr0rGv15Fpt4GCiNXwLRhnaeIg6kknNvbpQRkTR_9siGk4WL3ci5dfR-T1Vq6ihAicI2wPtE23mVKMHooAPxRGXPX4X7FIxomFYQ7k5vXaFkO3JTfvuVb2kPq4P-xgtqBbkB_oPYyu0PGQgBngnXggu9E3YxsZsxWrzPcyvzFH1dl1h684EGk6Prberte3c2n0Mez8Ee9YYBPN-oF5FpA0de6YHj1GkO50PpUmSeEYivW5HPNhIAagjrmAez1yQ6FPivKIjrz3FKy9qe-ZhU44RT5kireF585ARDiYInIa5RTbhmf0JV8xA1aICrapjoYSoM5Ghyooa4XhN9I1n6qoaUhOUw3mXxDIHYHf9wPyJdZ-bu43LMXjT4NgWlqX09MdfbhG4eQOvJwEONkqYTWpSegR5ZP06aqELiegZnFeVsGgD6O1QWcoiDYxaIbwdDwoQzxv2ij0Lk8LNOzScQGLQatNam7ncY3Zf2Uvg7m4ps1FSsWJyjU5t4uy7UAj5XCUrjHUaDeoistMi0nqOc-Yk5mpvWQ"
}
An ordinary Arweave native transaction is shown above, and the transaction information is explained below:
format
:Transaction format, the current Arweave transaction format always set to 2.id
:The hash of this transaction.last_tx
:An anchor,used to prevents replay attacks. Typically the hash of one of the last 50 blocks, or the last outgoing transaction ID of the sending wallet. An empty string can be used if this is the first transaction from the wallet.owner
:RSA public key.tags
:Custom tags of the transaction. for example, the tags above are {"name":"ContentType", "value":"img/png"}, but the value you can see above is the base64Url encoded value, so you need to decode it to see the true value.target
:The transfer address, if you just send data to Arweave, the value can be empty.quantity
:Transfer amount, the unit is winston, 1 AR = 10^12 winston.data
:Transaction data, this field is empty when obtaining transaction metadata.data_size
:The size of the transaction data, in bytes.data_root
:Merkle root hash of transaction data.reward
: The miner fee for this transaction.signature
: Signature of transaction.
Get Transaction Status
arId := "sUfG7jvu7PBQptlSIxtl6t5zD9LBMxv66_uVAlBk8dU"
status, err := cli.GetTransactionStatus(arId)
if err != nil {
panic(err)
}
fmt.Println(status)
return:
{
"block_height": 1003308,
"block_indep_hash": "jmvPK-uRUQH93Xx6D4LrAktVEkYCo_3kytFlgo0hMpV0dNWx0AWKzmQ2OlRwLPqc",
"number_of_confirmations": 40
}
This method will return the block height of the transaction, the block hash, and the number of nodes confirmed.
Get Transaction Tags
arId := "sUfG7jvu7PBQptlSIxtl6t5zD9LBMxv66_uVAlBk8dU"
tags, err := cli.GetTransactionTags(arId)
if err != nil {
panic(err)
}
fmt.Println(tags)
return:
[{Content-Type image/png}]
When obtaining transaction metadata above, the transaction Tags we obtained were encoded, and the Tags we obtained here are decoded and readable Tags.
Get Transaction Data
extension := "png"
arId := "sUfG7jvu7PBQptlSIxtl6t5zD9LBMxv66_uVAlBk8dU"
data, err := cli.GetTransactionData(arId, extension)
if err != nil {
panic(err)
}
fmt.Println(data)
return: data of the transaction.
note:
extension
is optional,e.g. png,txt.- If the transaction data is larger than 12M, goar will efficiently obtain the data through chunks.
Get Transaction Fee
target := "An AR addr or nil"
txData := "txData"
data, err := cli.GetTransactionPrice([]byte(txData), &target)
if err != nil {
panic(err)
}
fmt.Println(data)
return: AR (unit is winston) to be paid for this transaction, the main purpose of the payment is to upload data to arweave and store it permanent.
note:
txData
is the data carried by the transaction, which can be read through file IO.target
Is the transfer address, the value is nil if only send data to Arweave.
Get Tx_anchor
anthor, err := cli.GetTransactionAnchor()
if err != nil {
panic(err)
}
fmt.Println(anthor)
return:
nE7kAIYYzIZ_4_xbxidX_WmzntSuGsnc-MMmf6tmeYVdT0b-i5X5pVGB95MIg3bw
note:
tx_anchor
is mainly used to fill in thelast_tx
field when constructing a transaction. This value is generally the hash value of one of the last 50 blocks. It can be used to determine whether the AR transaction has expired to prevent replay attacks.
Submit AR Transaction
tx := <AR Tx>
body, statusCode, err := cli.SubmitTransaction(tx)
note:
This method is mainly used by other modules (the module will assemble the AR transaction) to call this method. Generally, it is not necessary to directly New a client instance to call this method.
Submit Chunk
chunk := <AR data chunk>
body, statusCode, err := tt.Client.SubmitChunks(chunk) // always body is errMsg
note:
Like submitting an AR transaction, this method is also called by other modules (which divide the data into chunks).
Conditional Query
qry := `{
transactions(ids: ["G-1t0Lqysin897HC3IV8xu_Mr884B-Mo5YEnlhUH54k"]) {
edges {
node {
id
block {
id
timestamp
}
}
}
}
}`
res, err := cli.GraphQL(qry)
if err != nil {
panic(err)
}
fmt.Println(string(res))
return:
{
"transactions":{
"edges":[
{
"node":{
"block":{
"id":"_W3jArV87Kzuf_VXHzgOgtivmtHTt26QD5jbwH9DPuxfa7KvTaWykeup_UKMv1zZ",
"timestamp":1600878676
},
"id":"G-1t0Lqysin897HC3IV8xu_Mr884B-Mo5YEnlhUH54k"
}
}
]
}
}
note:
qry
is query conditions, in this example, we query the block hash and timestamp corresponding to the specified arId. For more query examples, please refer to graphQL.
Get Account Balance
addr := "NVkSolD-1AJcJ0BMfEASJjIuak3Y6CvDJZ4XOIUbU9g"
bal, err := cli.GetWalletBalance(addr)
if err != nil {
panic(err)
}
fmt.Println(bal)
return:229.422694029987
note:
addr
:Arweave address.bal
: account balance,unit is AR.
Get The Last Transaction
addr := "NVkSolD-1AJcJ0BMfEASJjIuak3Y6CvDJZ4XOIUbU9g"
txId, err := cli.GetLastTransactionID(addr)
if err != nil {
panic(err)
}
fmt.Println(txId)
return:arId.
note:Get the last AR transaction id of the specified address.
Get Block Information by Block Hash
id := "rEPeabLpDO_2y6tsNVvwHRjJNYYHgVz9oqyLhXM-3QjUzTtePPy1sOIpmnn57OY0"
block, err := cli.GetBlockByID(id)
if err != nil {
panic(err)
}
fmt.Println(block)
Get Block Information by Block Height
height := 510788
block, err := cli.GetBlockByHeight(height)
if err != nil {
panic(err)
}
fmt.Println(block)
return:
{
"nonce": "gyms_ZAPH3conbCKIRm8JuODAtp8NlD3aBaLdCsp--I",
"previous_block": "u1dfjcN3yH37oRN96CfUvVf7V0w7zoQ233JNgMXS_XWZhXTsibwCprbXcvp5G3io",
"timestamp": 1597905785,
"last_retarget": 1597904281,
"diff": "115792089225334907412622155393890012047568246338521059128782635418398016667648",
"height": 510788,
"hash": "_____9BbiDatEnH3djvX0-NhBGA28NEWnjDIWLCkiB8",
"indep_hash": "rEPeabLpDO_2y6tsNVvwHRjJNYYHgVz9oqyLhXM-3QjUzTtePPy1sOIpmnn57OY0",
"txs": [
"-NR_WOHN7feR53D5Sco-U8uQtw_1x5jENmcp0N-EOhk",
.......................
"2ZSx2Ast1AmBYKBotKHvdh3BnZq9vLxnwmd9M49UQDI",
],
"tx_root": "L-f7g24O5lHA5onKbmFmRbyKZ0R_dXboW7AZmPBo2iI",
"tx_tree": [],
"wallet_list": "ZekJxJrqTWIUkAxkYZt_yxS1Yvyp_9p1Y0VMrZlIMFz0dvXamtOaZNgr8ZLkFHN7",
"reward_addr": "V12aL_AA2IiL3ltx44e4TTVQXuEaSdgy3qswrToFcJc",
"tags": [],
"reward_pool": 5119213831149206,
"weave_size": 1160387834901,
"block_size": 50468816,
"cumulative_diff": "469151620099952",
"hash_list_merkle": "Vrd5HYeH1O3XVCkFqWrBRcZgX8A_ItyUwdpNgrh5PYF-tChDUqXj2rMoh7khJEJg",
"poa": {
"option": "1",
"tx_path": "-JFwjXN41_SRo8PFA6W1p-hk_hpFBRZZDGTT24Z5hg202t7EcuyZV9u02Wsv_82VO6YCCm6iReJO_I51X0m0PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMlStkRI-8YKz8VmNSwYEYMH2YL-Pjney2JX31ACcb6bwrPjIjg2BdHYXe9-FUsLhlA7xVTsA7Qsyux3qWv2amP0LZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAShVGoMskgWgBd-tBILt01zNBb-zRJmG66T6_byUU7vM5LSfvB70FgAtCPFMy7-XkRHIkAX8b-o-HB-iOAE5RFxzBEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOhMKikwMvPZvB3Khu29C51mNhl1wcj-ZGMCriJ6Xw3khoX4UsGGdPv5N6lsUAtLofG7Ard5GS1HrSidKG47JucgQdQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAShPSTbG2LFU-qJ57Hl-ADcGPFV1PyR6ePNg5B9L2kYFZ_JgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEoT0g",
"data_path": "hrxipQs9CNZOuUnxZn3uYHr2oIGUKYhyKny9rDdttmrbpOzVkObe7bpVeAG0U62w1h-ixPFGse9BMz294MTKXwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAjS-HxbUwp9VESWe2tOi5CZj1Jg52kS_pJ9PIzGx4Q6IWxcmyQBaIWtZ3X2izltsBIf-oEMoAX3TV6Rd9pWmQiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAeOxWCbG1qLKw41g-KBLEC0g6Xfo58MC88OqHBhpJEvph4kbJT5vSt6nkjRYp2NaHr-xFdW_DgbxW3NuEKiOs8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAS2pyAEkkplSfU4ciSdbMUexYmGoK_kv_CoYKQbdk8PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA",
"chunk": "PCFET0NUWVBFIGh0bWw-PGh0bWwgbGFuZz0iZW4tVVMiIHByZWZpeD0ib2c6IGh0dHA6Ly9vZ3AubWUvbnMjIiBzdHlsZT0idHJhbnNmb3JtOiBub25lOyI-PGhlYWQ-PG1ldGEgY2hhcnNldD0iVVRGLTgiPjxtZXRhIGh0dHAtZXF1aXY9IlgtVUEtQ29tcGF0aWJsZSIgY29udGVudD0iSUU9......"
}
}
Get Transaction by Specific Fields
field := "data.png"
data, err := cli.GetTransactionField("sUfG7jvu7PBQptlSIxtl6t5zD9LBMxv66_uVAlBk8dU", field)
if err != nil {
panic(err)
}
fmt.Println(data)
return: transaction data.
note:
field
The parameters that the field can accept are:id,last_tx,owner,tags,target,quantity,data,data_root,data_size,reward,signature and data.{extension}
.