Skip to content
aleqx edited this page Oct 17, 2019 · 50 revisions

New API docs for v2.x

https://docs.rs/grin_wallet_api/2.0.0/grin_wallet_api/

Below are old (obsolete) API docs for v1.x

Warning1

RECENT CHANGES:

  • (30 Jun 2019) Obsoleted since Grin Wallet v2.0.0
  • (7 Feb 2019) Creation for Grin v1.0.x

Grin Wallet API Guide

General Information

This doc is for the Grin wallet API practical usage guide, not the wallet API doc. For detailed wallet APIs reference, please read doc Wallet Owner API and Wallet Foreign API.

Wallet Configuration

By default, the wallet configuration file ~/.grin/main/grin-wallet.toml will be automatically generated on the 1st run of grin-wallet. Floonet configuration is stored in a separate directory (~/.grin/floo).

Note: On all following introductions, I will only write main for mainnet. If you're runing Floonet, please remember to replace main as floo.

Some default configuration need to be modified according to your practical requirements:

1. Chain Type

#Floonet - For the long term Floonet test network
chain_type = "Mainnet"

Please double check the chain_type here is configured as Mainnet.

Floonet is only for the test network.

2. Listen Interface:

#host IP for wallet listener, change to "0.0.0.0" to receive grins
api_listen_interface = "0.0.0.0"

And remember to double check the listening interface after you start wallet listening:

netstat -tlna | grep 3415

For example, my output is:

tcp        0      0 127.0.0.1:3415          0.0.0.0:*               LISTEN 

that means my wallet's listening on localhost only.

Note: For send-only wallet, it's OK to keep api_listen_interface = "127.0.0.1" as the default configuration for it.

3. API Secrets

On the 1st time running of grin, a random API secret will be generated into ~/.grin/main/.api_secret file. You can use your own secret but please make sure using some kinds of password generator to ensure this secret has enough complexity.

#path of the secret token used by the API to authenticate the calls
#comment it to disable basic auth
#api_secret_path = "/home/garyyu/.grin/main/.api_secret"

#location of the node api secret for basic auth on the Grin API
#node_api_secret_path = "/home/garyyu/.grin/main/.api_secret"

#where the wallet should find a running node
check_node_api_http_addr = "http://127.0.0.1:3413"

These are my configurations, and yours should be different on the home directory name.

As you see, I disabled the wallet API secret, this disable is ONLY for the following demos (for simple) and this API secret is strongly suggested on the production environment. Same for the node API secret. (node means a Grin server)

Regarding the check_node_api_http_addr, in my case I have a Grin server running on same server, so I can use "http://127.0.0.1:3413". If you're using an external Grin server, you can modify this to point to your Grin server. 3413 is the default node API port.

4. HTTPS

For the wallet which is listening on external network interface, it's a MUST to enable the https, unless you know exactly what you're doing by HTTP!

To enable https, we only need to configure the following TLS certificate files:

#path of TLS certificate file, self-signed certificates are not supported
tls_certificate_file = "/etc/letsencrypt/live/demo.grin.icu/fullchain.pem"
#private key for the TLS certificate
tls_certificate_key =  "/etc/letsencrypt/live/demo.grin.icu/privkey.pem"

Please replace these files with your own TLS certificate files.

If you want to use letsencrypt like me, you can refer to the Wallet TLS Setup Guide.

BTW, we will do some enhancement on this in the future, refer to #2523 for the detail.

5. Wallet Data File Directory

By default, grin wallet will create wallet data folder in ~/.grin/main/wallet_data. And you can modify this folder as you want, to put wallet_data into any location.

#where to find wallet files (seed, data, etc)
data_file_dir = "/home/garyyu/.grin/main/wallet_data"

In this wallet_data, you will find 3 types of files:

  • wallet database files: lmdb database.
  • wallet.seed: the encrypted wallet seed file.
  • saved_txs: the folder to save those raw transaction data, in file format, with the Shared Transaction Id (i.e. an UUID) as the file name. Note: only those sending transactions have the corresponding saved_txs file, and the purpose of this saved raw transaction data is for reposting, in case any failure of previous post_tx.
Here is an example in this `wallet_data` folder: (Click to expand)

$ tree  ~/.grin/main/wallet_data/
/home/garyyu/.grin/main/wallet_data/
├── db
│   └── lmdb
│       ├── data.mdb
│       └── lock.mdb
├── saved_txs
│   ├── 205d9cde-af28-44ff-b425-3be4a7e939dd.grintx
│   ├── 4caee644-f8d1-4f5c-b3af-f11de5a41586.grintx
│   ├── 507aa335-246d-4d6c-84bb-2516fb8e44ac.grintx
│   ├── 78efaa87-f7c2-4fde-a14b-68338f9c32fd.grintx
│   ├── 8ba033b6-3e05-4cad-81ec-937f3056b1e8.grintx
│   ├── 8d2fc370-b442-41a5-b889-715a1dae9cf2.grintx
│   ├── 8e298bd0-2bd5-4184-a810-3d0a9f6086b8.grintx
│   ├── a063be0e-7523-4a1c-a993-ae3592c10191.grintx
│   ├── b55a062a-32b4-45d1-b4d9-f921f922555a.grintx
│   └── edea1387-a797-4a50-92b5-4cdadfae6052.grintx
└── wallet.seed

5. Log Output

I suggest to enable both stdout and file log, as follows. And stdout_log_level = "Info", the "Info" level is better than "Warning" level for stdout, because with this you will get some immediate useful feedbacks when using some grin wallet command.

#whether to log to stdout
log_to_stdout = true

#log level for stdout: Error, Warning, Info, Debug, Trace
stdout_log_level = "Info"

#whether to log to a file
log_to_file = true

#log level for file: Error, Warning, Info, Debug, Trace
file_log_level = "Debug"

Wallet Sending via API

Before we can call the following wallet API, we need run a grin wallet listening on owner api:

$ grin-wallet owner_api

Note: please run this grin-wallet owner_api command from a designed folder and which folder will also be used to store some possible temporary files (when using file method).

Http/s Method

1st Step

Construct a JSON format parameters.

For example:

{
  "amount": 110000000, 
  "minimum_confirmations": 10,
  "method": "http",
  "dest": "https://demo.grin.icu:3415",
  "max_outputs": 500,
  "num_change_outputs": 1,
  "selection_strategy_is_use_all": true
}

For the detailed parameter description, please refer to issue_send_tx API doc.

Some additional notes on above parameters:

  1. amount is using Nano Grin as unit, i.e. 10^-9 Grin. For example, the amount 110000000 here means 0.11 Grin coins.
  2. both https and https share the same method name: http.
  3. "dest": "https://demo.grin.icu:3415" here is using https. If you need use http, just modify the url as http://....
  4. For a simple case, normally we have one change output for self and another output for payee, that's why in this example I set "num_change_outputs": 1.
  5. "selection_strategy_is_use_all": true is the proposed setting (to make the chain has the minimum UTXO sets). But if you have multiple payments need to be done quickly, you can set it as false. Because with true, we will get all the balance locked until current transaction is confirmed on the chain (that's 10 blocks or about 10 minutes). With "selection_strategy_is_use_all": false, only part of UTXOs (sum up to be able to pay the amount) will be used.
  6. "max_outputs" here means the maximum UTXOs can be used for this transaction. And it's a soft limit, when this is not enough to cover the whole output amount, the wallet will include more outputs. The proposed value here is 500.

2nd Step

Call the issue_send_tx API with above parameters.

Let's use curl for a demo here on calling this API, if we save above JSON parameters into a file issue_send_tx-1.json:

$ data=`cat issue_send_tx-1.json`; curl -0 -XPOST http://127.0.0.1:3420/v1/wallet/owner/issue_send_tx  -d "$data" 2>/dev/null  | jq

Note: In production environment with API secret, the above curl would be curl -0 -XPOST -u grin:"$api_secret" http://... , i.e. add -u grin:password.

The output example: (Click to expand)

{
  "num_participants": 2,
  "id": "8ba033b6-3e05-4cad-81ec-937f3056b1e8",
  "tx": {
    "offset": [...],
    "body": {
      "inputs": [
        {
          "features": "Plain",
          "commit": [...],
        }
      ],
      "outputs": [
        {
          "features": "Plain",
          "commit": [...],
          "proof": [...],
        },
        {
          "features": "Plain",
          "commit": [...],
          "proof": [...],
       }
      ],
      "kernels": [
        {
          "features": "HeightLocked",
          "fee": 8000000,
          "lock_height": 18187,
          "excess": [...],
          "excess_sig": [...],
       }
      ]
    }
  },
  "amount": 110000000,
  "fee": 8000000,
  "height": 18187,
  "lock_height": 18187,
  "participant_data": [
    {
      "id": 0,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null
    },
    {
      "id": 1,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null
     }
  ]
}

3rd Step

Call the post_tx API with above outputs from 2nd step. Refer to detailed info in Post Tx API Doc.

Suppose we save above JSON format output as a file post_tx_1.json, then, let's still use curl to simulate this API call:

$ data=`cat post_tx-1.json`; curl -0 -XPOST http://127.0.0.1:3420/v1/wallet/owner/post_tx?fluff  -d "$data" 2>/dev/null  

Note: In above usage demo, I use ?fluff to bypass the Dandelion relay, but it's not proposed.

Then, in normal case, a wallet sending (payment) is done. We will discuss how to handle the exception cases in How to Collaborate Sending and Query.

File Method

For some use cases, the file method is useful. For example, payment by email, or by file download/upload plus a finalize step, in which case the user will login to the website and request a payout, and then download a raw transaction file, then execute a receive on his/her local Grin wallet, and then upload the output file, and the website will call the finalize once the uploading is completed, and call the last step post. Payment by email is similar.

1st Step

Construct a JSON format parameters.

For example:

{
  "amount": 120000000, 
  "minimum_confirmations": 10,
  "method": "file",
  "dest": "file1.json",
  "max_outputs": 500,
  "num_change_outputs": 1,
  "selection_strategy_is_use_all": true
}

Note: the generated file file1.json will be in the same folder as you run the grin-wallet owner_api.

2nd Step

This should be executed by the payment receiver! Remember that the Grin transaction is an interactive procedure.

Suppose the payee already downloaded the file file1.json, and ask him/her to run following command on his local wallet:

$ grin-wallet receive -i file1.json

and this command will generate file file1.json.response, in the same folder as file1.json.

Then the payee need upload this file1.json.response file to the payer.

3rd Step

Once the payer received above uploaded file file1.json.response, call the finalize_tx API with the file. For detailed info about this API, refer to finalize_tx API Doc.

Still use curl to simulate this API call:

$ data=`cat file1.json.response`; curl -0 -XPOST http://127.0.0.1:3420/v1/wallet/owner/finalize_tx -d "$data" 2>/dev/null  | jq

The output format is similar as the output of issue_send_tx API output, so I will not paste here.

4th Step

We need call the post_tx API with the finalize_tx API outputs from 3rd step. Refer to detailed info in Post Tx API Doc.

Suppose we save above JSON format output as a file post_tx_2.json, then, let's still use curl to simulate this API call:

$ data=`cat post_tx-2.json`; curl -0 -XPOST http://127.0.0.1:3420/v1/wallet/owner/post_tx?fluff  -d "$data" 2>/dev/null  

Same comments as before about the ?fluff.

Then, in normal case, a wallet sending (payment) is done. We will discuss how to handle the exception cases in How to Collaborate Sending and Query.

Keybase Method

Grin wallet support Keybase plugin method, using Keybase encrypted private communication channel as a safe transmitting tool. It's a better method that Http/s for those users whose grin wallet is under NAT and hard to open a port on router or firewall, and easy to use. And comparing to File method, this Keybase method is more efficient because it's a realtime processing.

To use Keybase plugin, both the sender and the receiver must have Keybase installed and running, and of course a Keybase account is needed and keep it login. Propose to use keybase status command to double check the following status of keybase, before sender start making a payment with keybase method:

$ keybase status

The output should contains the following:

...
Logged in:     yes

Device:
    ...
    status:    active

Service:
    status:    running

The steps of using this keybase method to make a payment are almost same as HTTP/s method, the difference is:

  1. The receiver must have grin wallet listening on keybase plugin.
$ grin-wallet listen -m keybase
  1. The constructed JSON format parameters for the 1st step is a little bit different:

For example:

{
  "amount": 150000000, 
  "minimum_confirmations": 10,
  "method": "keybase",
  "dest": "gringod",
  "max_outputs": 1,
  "num_change_outputs": 1,
  "selection_strategy_is_use_all": false
}

Note:

  • "method": "keybase"
  • dest here must fill the receiver's keybase account name, for example gringod here in above example.

then, for the 2nd step (call the issue_send_tx API with above parameters) and the 3rd step (call post_tx API to post the transaction to the chain) are same as HTTP/s method.

Important Notes for Keybase method:

  • For saving the CPU load, the Keybase communication channel polling has a long interval (about 5 seconds) by default, and a long TTL (about 60 seconds), so it's not efficient if you need call a payment frequently especially in batch payment case.
  • But these timers can be adapted for much better performance in this special use case, please contact us if need further suggestions on this.

Wallet Query APIs

Transactions Query

We can use retrieve_txs API for transactions query, normally this is the 1st step in a query, if we start from the Shared Transaction Id (i.e. wallet transaction UUID). For detail info of this API, refers to retrieve_txs API doc.

Let's simulate this API call with curl:

$ curl -0 -XGET http://127.0.0.1:3420/v1/wallet/owner/retrieve_txs?tx_id=e2195b2c-9fd5-442b-86ce-8c7693671484 2>/dev/null | jq
The output example for above command: (Click to expand)

[
  false,
  [
    {
      "parent_key_id": "0200000000000000000000000000000000",
      "id": 0,
      "tx_slate_id": "e2195b2c-9fd5-442b-86ce-8c7693671484",
      "tx_type": "TxReceived",
      "creation_ts": "2019-01-28T00:01:00.122919Z",
      "confirmation_ts": null,
      "confirmed": false,
      "num_inputs": 0,
      "num_outputs": 1,
      "amount_credited": 1000000000,
      "amount_debited": 0,
      "fee": null,
      "stored_tx": null
    }
  ]
]

Note:

  1. The tx_id here is the Shared Transaction Id for wallet, it's a local generated random UUID, and this UUID is not stored in the blockchain (please don't mix it with Bitcoin/Ethereum TxId concept).
  2. When using wallet API for payment, it's important to cache this UUID, so as to query the transaction status with this UUID, for example using it here.
  3. In this example, it's a TxReceived transaction, so some fields are invalid such as num_inputs, fee, and stored_tx. As you see, this transaction status is "confirmed": false, that means it's pending on payer side to post it.

Let's take another example here for a TxSent transaction:

$ curl -0 -XGET http://127.0.0.1:3420/v1/wallet/owner/retrieve_txs?tx_id=8e298bd0-2bd5-4184-a810-3d0a9f6086b8 2>/dev/null | jq
The output example for above command: (Click to expand)

[
  false,
  [
    {
      "parent_key_id": "0200000000000000000000000000000000",
      "id": 1,
      "tx_slate_id": "8e298bd0-2bd5-4184-a810-3d0a9f6086b8",
      "tx_type": "TxSent",
      "creation_ts": "2019-01-28T00:23:20.025622Z",
      "confirmation_ts": "2019-01-28T00:28:23.305599Z",
      "confirmed": true,
      "num_inputs": 1,
      "num_outputs": 1,
      "amount_credited": 892000000,
      "amount_debited": 1000000000,
      "fee": 8000000,
      "stored_tx": "8e298bd0-2bd5-4184-a810-3d0a9f6086b8.grintx"
    }
  ]
]

Note:

  1. For TxSent type transactions, the stored_tx contains the file name which stored the raw transaction data, the file location is in ~/.grin/main/wallet_data/saved_txs by default.
  2. fee is the transaction fee of this transaction. 0.008 Grin is a typical fee for a transaction with 1 input and 2 outputs (1 change plus 1 output for receiver).
  3. amount_debited is the sum of all inputs amount. It's 1.0 Grin in this example.
  4. amount_credited is the your own change output amount. It's 0.892 Grin in this example, and amount_debited - amount_credited - fee is the paid amount in this transaction.
  5. "confirmed": true here just means this transaction has been picked up in the chain, you still need check the output status to get the confirmation numbers, with retrieve_outputs API.
  6. "id": 1 refers to the tx_log_entry, which will be used for retrieve_outputs API (next chapter).

Outputs Query

We can use retrieve_outputs API for outputs query, normally this is the 2nd step in a query, if we start from the Shared Transaction Id (i.e. wallet transaction UUID). For detail info of this API, refers to retrieve_outputs API doc.

To simulate this API call with curl:

$ curl -0 -XGET http://127.0.0.1:3420/v1/wallet/owner/retrieve_outputs?refresh\&show_spent\&tx_id=1 2>/dev/null  | jq

In this example, we query the transaction with tx_log_entry = 1, and with refresh to refresh the transaction status from Grin server (node) with node API, and with show_spent to show the Input(s) of this transaction.

The output example for above command: (Click to expand)

[
  true,
  [
    [
      {
        "root_key_id": "0200000000000000000000000000000000",
        "key_id": "0300000000000000000000000000000000",
        "n_child": 0,
        "commit": "090ece191f5e29c1ab07cdf8f51a0e464d0d4bab3eeeeb01ffaf106f09e33ade98",
        "mmr_index": null,
        "value": 1000000000,
        "status": "Spent",
        "height": 17587,
        "lock_height": 0,
        "is_coinbase": false,
        "tx_log_entry": 1
      },
      [...(33 bytes commit data)...]
    ],
    [
      {
        "root_key_id": "0200000000000000000000000000000000",
        "key_id": "0300000000000000000000000400000000",
        "n_child": 4,
        "commit": "0888738231e755c348b512e681b6147c6d4f37e8d7054d2ffc700d7ea38c945341",
        "mmr_index": null,
        "value": 892000000,
        "status": "Unspent",
        "height": 17609,
        "lock_height": 0,
        "is_coinbase": false,
        "tx_log_entry": 1
      },
      [...(33 bytes commit data)...]
    ]
  ]
]

Note:

  1. In this example, the input commitment and output commitment can be found in the explorer.
  2. You can find this transaction in block 17609.
  3. In this example, the input is 1.0 Grin coin, and the output (it's the change output here) is 0.892 Grin coin, where's another leg? :) the answer is the retrieve_outputs wallet API is used to retrieve your own outputs! and the status (confirmed / unconfirmed) of another leg (or other outputs) is same as your own change output, because all outputs in one transaction share same transaction kernel, i.e. they're in same transaction.
  4. Then, how to query the outputs you sent to receiver? the answer is: retrieve_stored_tx API, we will show the usage in next section.
  5. Please note that, for your own outputs, there're two types: one is spent output, another is unspent output (i.e. UTXO). To avoid showing a long history, the grin-wallet outputs command will only show the Locked | Unspent | Unconfirmed outputs by default. We can use -s option to show also the spent outputs, i.e. grin-wallet -s outputs, to get same result as in this example.
  6. For spent outputs, another note is: it will be bound to same tx_log_entry as the spent transaction. In this example, you can see the tx_log_entry=1 and it include both your spent output/s (i.e. Input/s) and your change output/s.
  7. The first element true is the validated status. With refresh parameter in this API call, this true means the output status is validated on the chain, via node API.
  8. The returned value looks like not in a pure JSON format, this could deserve an improvement in the future, will submit an issue on this (if not having). And the [...(33 bytes commit data)...] part is the duplication of "commit".

And regarding the output status, totally we have 4 status:

  • Unconfirmed
  • Unspent
  • Locked
  • Spent

Transactions / Outputs Confirmation Query

With retrieve_txs API, we can get something like "confirmed": true for a transaction status. And with retrieve_outputs API, we can get something like "status": "Unspent" for an output status. But an important concept for blockchain transaction is the confirmations, that means how many consequent blocks have been mined after this transaction included in one block.

So, both above "confirmed": true and "status": "Unspent" just means the outputs have been included in the chain, and we still need query the confirmations for this transaction / output, normally this is the 3rd step in a query, if we start from the Shared Transaction Id (i.e. wallet transaction UUID).

To query the confirmations of an output, propose to use node API chain/outputs/byids with the unspent output commitment, normally this "unspent output" is either the change output in a sending transaction, or the received output in a receiving transaction. And please remember you can't query a spent output commitment on the chain, because of MimbleWimble cut-through feature.

For example:

Step 1

Suppose we got an unspent output commitment with retrieve_outputs API:

$ curl -0 -XGET http://127.0.0.1:3420/v1/wallet/owner/retrieve_outputs?refresh\&show_spent\&tx_id=9 2>/dev/null  | jq

part of the outputs:

      {
        "root_key_id": "0200000000000000000000000000000000",
        "key_id": "0300000000000000000000000e00000000",
        "n_child": 14,
        "commit": "08cef2eee0ee9b8ff79d3fabf63da57e520255c749553c2ac72b874c1e8d7a02cb",
        "mmr_index": null,
        "value": 174333334,
        "status": "Unspent",
        "height": 32344,
        "lock_height": 0,
        "is_coinbase": false,
        "tx_log_entry": 9
      },

Step 2

Repeat step 1 until its status becomes Unspent, then we call node API chain/outputs/byids with this commit to query whether it's still on the chain:

$ curl -0 -XGET http://127.0.0.1:3413/v1/chain/outputs/byids?id=08b5c829f81cdf2a1f600517907607f22591ef96673b1145f6b5d0eda425cb4df8 2>/dev/null | jq

The output of above query:

[
  {
    "commit": "08b5c829f81cdf2a1f600517907607f22591ef96673b1145f6b5d0eda425cb4df8",
    "height": 32344,
    "mmr_index": 646506
  }
]

Note: for the details of this node API, please refer to Node API Doc.

Step 3

Repeat step 2 (in every minute for example) until the node height is high enough, i.e. node_height - output_height > minimum_confirmations.

output_height is 32344 in this example.

minimum_confirmations can be your self configuration, at this moment, the proposed minimum confirmations value is 10.

And we can query node_height by node_height API:

$ curl -0 -XGET http://127.0.0.1:3420/v1/wallet/owner/node_height 2>/dev/null | jq

At this moment (when writing this wiki), the output could be:

[
  34191,
  true
]

When node_height - output_height > minimum_confirmations is true, the query loop can stop and the output status is finalized.

Note: for the details of this API, please refer to Node Height API Doc.

Wallet Summary Query

To get the same info as the grin-wallet info command, we can use retrieve_summary_info API.

$ curl -0 -XGET http://127.0.0.1:3420/v1/wallet/owner/retrieve_summary_info?refresh\&minimum_confirmations=10 2>/dev/null | jq

An example output:

[
  true,
  {
    "last_confirmed_height": 32427,
    "minimum_confirmations": 10,
    "total": 118125000000,
    "amount_awaiting_confirmation": 0,
    "amount_immature": 0,
    "amount_currently_spendable": 118125000000,
    "amount_locked": 0
  }
]

And compare it with the command grin-wallet info:

$ grin-wallet info --min_conf=10
Password: 

____ Wallet Summary Info - Account 'default' as of height 32427 ____

 Total                            | 118.125000000 
 Awaiting Confirmation (< 10)     | 0.000000000 
 Locked by previous transaction   | 0.000000000 
 -------------------------------- | ------------- 
 Currently Spendable              | 118.125000000 

Collaborate Send/Receive and Query/Cancel/Post

In production environment, there're always some exception cases which sending/receiving can't finish. The possible reasons here but not limited:

  • For Sending
    1. The receiver is not ready to receive, such as wallet is not listening, unreachable under NAT, etc.
    2. The transaction posting failed for some reasons, so the transaction status stays in Unconfirmed for ever.
  • For Receiving
    1. The sender didn't finish the remaining steps (i.e. finalize and posting) of a transaction, so the received output always shows as Unconfirmed.
    2. The sender double spent an output.

On these exception cases, we need call cancel_tx or post_tx API, depending on the actual query status. For query steps, please refer to Transaction/Output Confirmation Query.

Cancel a Transaction

For an Unconfirmed sending transaction, we can call cancel_tx API to cancel it. Refer to Cancel Tx API Doc for detail.

An example to call this API:

$ curl -0 -XPOST http://127.0.0.1:3420/v1/wallet/owner/cancel_tx?id=2 2>/dev/null  | jq

To avoid the racing exception, either you're sure this transaction can't finish, or waiting enough time before you cancel it.

Re-Posting a Transaction

For an Unconfirmed sending transaction, if you make sure the previous posting doesn't work (for example you already waited 2 minutes but the transaction status is still Unconfirmed), you can call repost API to try re-posting it to the chain. The re-posting is a safe operation.

In case of this transaction is already included on the chain, the repost API will get 500 Internal Server Error, with an error message failed to validate tx.

For detail of this repost API, refer to Repost API Doc.

To simulate this API call here with curl:

$ curl -0 -XPOST http://127.0.0.1:3420/v1/wallet/owner/repost?id=2 2>/dev/null

And you can use UUID instead of the entry id. Also, the fluff parameter is feasible here.

This API is identical to the command grin-wallet repost, refer to repost command usage.

Special Use Cases

Batch Payment

For example, in mining pool use case, we could setup an automatic payout on a scheduled periodic time, and we need make hundred/thousand payments in one time. Surely there're also a lot of other similar batch payment use cases like this.

The batch payment (i.e. multiple receivers for one transaction) feature is planed in the future release. At this moment (for version 1.0.x), we only can pay one receiver for one transaction.

Because we need wait 10 confirmations (suppose we set minimum_confirmations=10) for each transaction, the wallet balance will be locked for about 10 minutes after we did one transaction. That's quite inconvenient and inefficient for batch payment use case.

But we have a workaround solution here, before we release the real batch payment feature.

The basic idea is to split our wallet balance before we do the batch payment.

For example, if we have total 2,004 spendable Grin coins in the wallet, and we need do a 1,000 receivers batch payments, and suppose every payment is less than 2 Grin coins, then we can do it at the following steps:

1. Split Wallet Outputs

We can use issue_send_tx API to generate 1,000 UTXOs for ourselves at one time.

Construct a JSON format parameters:

{
  "amount": 2000000000, 
  "minimum_confirmations": 10,
  "method": "file",
  "dest": "split.1000.grin",
  "max_outputs": 1000,
  "num_change_outputs": 999,
  "selection_strategy_is_use_all": true
}

Note:

  • The num_change_outputs is the desired numbers minus one, since we have one receiver output on this transaction.
  • selection_strategy_is_use_all is true here, to ensure we use all the existing UTXOs for getting enough input balance.
  • "method": "file" is strongly suggested for this splitting, for safety.
  • Regarding the transaction fee of the splitting: in this example, the fee will be output_len * 4 + kernel_len - input_len = 1000 * 4 + 1 - 1000 = 3001 Milli-Grin (i.e. about 3.0 Grin Coins). So the estimated fee rate is about 0.15% in this example. (Note: here we suppose the total inputs number is also 1,000, it's a reasonable assumption since we most likely got one change output for one transaction.)
  • Before calling issue_send_tx API to execute this splitting, remember to use retrieve_summary_info API to retrieve the amount_currently_spendable and make sure the total spendable amount is enough for this splitting, including the fee.
  • The 999 split change output will have the same amount for each. That means we will get 999 UTXOs and each UTXO has an amount: (origin_total_spendable - fee - 2) / 999, in this example, it's (2004 - 3.001 - 2) / 999 = 2.001.

Then, for the remaining parts to finish this splitting transaction, we can follow the above guide: Wallet Sending via API (Method: File).

Remember to query the transaction / output status, and wait till 10 (for example) confirmations for this splitting transaction.

2. Make 1,000 Transactions with Generated 1,000 UTXOs

With the generated 1,000 UTXOs in step 1, we're ready to make 1,000 transactions to those 1,000 receivers. There's nothing special here compared to making a payment to one receiver, just follow those steps which has been introduced in Wallet Sending via API (and don't forget the Transaction/Output Confirmation Query and How to Collaborate Send/Receive and Query/Cancel/Post ), and make these payments one by one.

An important note is, please remember to set selection_strategy_is_use_all as false for these payments!

For example, the constructed JSON format parameters of a payment:

{
  "amount": 2000000000, 
  "minimum_confirmations": 10,
  "method": "http",
  "dest": "https://{one-receiver's address and port}",
  "max_outputs": 1,
  "num_change_outputs": 1,
  "selection_strategy_is_use_all": false
}

For wallet performance reason, depending on what kind of CPU your wallet's running, you could need sleep 1 or 2 seconds between each payment. Then, 1,000 payments could need 15 or 30 minutes to complete. If that can't reach your requirement, you can consider using multiple wallet instances for parallel calling, each wallet instance is a completely independent wallet with its own wallet_data, configuration file, and port.

Messages and Signature

[To Be Completed]

Clone this wiki locally