Skip to content

UFO wallet protocol API

ufo-project edited this page Apr 23, 2020 · 6 revisions

UFO wallet protocol API

Wallet API has the same structure as Node Stratum API protocol (JSON RPC 2.0 over TCP connection) and should have an online connection to the node. However, it can work over HTTP if you will use --api_use_http=1 option, send POST requests to http://x.x.x.x:port/api/wallet in this case.

How to use

Find wallet-api binary in the wallet subdirectory, place it near your wallet.db file and run with the following arguments:

Wallet API general options:
  -h [ --help ]                     list of all options
  -p [ --port ] arg (=10000)        port to start server on
  -n [ --node_addr ] arg            address of node
  --wallet_path arg (=wallet.db)    path to wallet file
  --pass arg                        password for the wallet
  --use_http arg (=0)               use JSON RPC over HTTP
  --ip_whitelist arg                IP whitelist

User authorization options:
  --use_acl arg (=0)                use Access Control List (ACL)
  --acl_path arg (=wallet_api.acl)  path to ACL file

TLS protocol options:
  --use_tls arg (=0)                use TLS protocol
  --tls_cert arg (=wallet_api.crt)  path to TLS certificate
  --tls_key arg (=wallet_api.key)   path to TLS private key
  --tls_request_cert (=false)       request client's certificate for verification for client authentication
  --tls_reject_unauthorized (=true) server will reject any connection which is not authorized with the list of supplied CAs
  • If you would like to run ufo-node on local for example
./ufo-node --treasury_path=treasury.bin --port=20015 --peer mainnet-node01.ufo.link:20015, mainnet-node02.ufo.link:20015, mainnet-node03.ufo.link:20015
./wallet-api --node_addr=127.0.0.1:20015 --pass=<your wallet pass>
  • If you just want to connect to public node for example
./wallet-api --node_addr=mainnet-node01.ufo.link:20015 --pass=<your wallet pass>
  • BTW: --api_use_http=1 make wallet-api work on HTTP-JSONRPC, and --ip_whitelist=127.0.0.1 make your wallet-api service access just only local environment.

Demo code

Here is a code on NodeJS to get all the UTXOs, for example:

var net = require('net');

var client = new net.Socket();
client.connect(10000, '127.0.0.1', function() {
	console.log('Connected');
	client.write(JSON.stringify(
		{
			jsonrpc: '2.0',
			id: 123,
			method: 'get_utxo',
			params: {}
		}) + '\n');
});

var acc = '';

client.on('data', function(data) {
	acc += data;

	// searching for \n symbol to find end of response
	if(data.indexOf('\n') != -1)
	{
		var res = JSON.parse(acc);

		console.log('Received:', res);

		client.destroy(); // kill client after server's response
	}
});

client.on('close', function() {
	console.log('Connection closed');
});

Curl POST example

If you use JSONRPC over HTTP you can do POST requests using CURL.

You will need to specify 'use_http=1' in wallet-api.cfg to enable HTTP mode

Here is an example to get current wallet status.

curl -d '{"jsonrpc":"2.0","id":1,"method":"wallet_status"}' -H "Content-Type: application/json" -X POST http://x.x.x.x:port/api/wallet

API

API will include the following methods:

create_address

Creates a new receiver address with given comment.

-->

{
	"jsonrpc" : "2.0", 
	"id" : 1,
	"method" : "create_address", 
	"params" :
	{
		"comment" : "John Smith"
	}
}

expiration and comment can be omitted.

<--

{
	"jsonrpc" : "2.0", 
	"id" : 1,
	"result" : "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67"
}

validate_address

Just base check, validates if the address isn't garbage and belongs our elliptic curve. Also returns is_mine == true if address is found in the wallet DB.

-->

{
	"jsonrpc":"2.0", 
	"id": 1,
	"method":"validate_address", 
	"params":
	{
		"address" : "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67"
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 1,
	"result" : 
	{
		"is_valid" : true,
		"is_mine" : false,
	}
}

addr_list

Get all the addresses in the wallet. Use own=true to get all the own addresses

-->

{
	"jsonrpc":"2.0", 
	"id": 8,
	"method":"addr_list",
	"params":
	{
		"own" : true
	}
}

<--

{
	"id": 8,
	"jsonrpc": "2.0",
	"result":
	[
		{
			"address":
			"29510b33fac0cb20695fd3b836d835451e600c4224d8fb335dc1a68271deb9b6b5b",
			"category": "",
			"create_time": 1553174321,
			"duration": 0,
			"expired": false,
			"comment": "",
			"own": true 
		}
	] 
}

delete_address

Delete specific address from the wallet.

-->

{
	"jsonrpc":"2.0", 
	"id": 8,
	"method":"delete_address",
	"params":
	{
		"address" : "29510b33fac0cb20695fd3b836d835451e600c4224d8fb335dc1a68271deb9b6b5b"
	}
}

<--

{
	"id": 8,
	"jsonrpc": "2.0",
	"result": "done"
}

edit_address

Edit specific address in the wallet, you can change the comment.

-->

{
	"jsonrpc":"2.0", 
	"id": 8,
	"method":"edit_address",
	"params":
	{
		"address" : "29510b33fac0cb20695fd3b836d835451e600c4224d8fb335dc1a68271deb9b6b5b",
		"comment" : "John Smith"
	}
}

<--

{
	"id": 8,
	"jsonrpc": "2.0",
	"result": "done"
}

tx_send

Sends transactions with a specific value to a given address.

-->

{
	"jsonrpc":"2.0", 
	"id": 2,
	"method":"tx_send", 
	"params":
	{
		"value" : 12342342,
		"fee" : 2,
		"from" : "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67",
		"address" : "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67",
		"comment" : "thank you!"
	}
}

value and fee are in Groth

from address can be omitted, new own address will be generated and registered in this case.

fee and comment can be omitted.

txId you can provide your own transaction ID.

You can also preselect specific UTXOs for a transaction by adding coins array parameter, like "coins" : ["00057e8eca5673476e6f726d000000000000015d3ef79800", "1f5df08a420fd7d06e6f726d010000000000000005f5e100"]

<--

{
	"jsonrpc":"2.0", 
	"id": 2,
	"result":
	{
		"txId" : "10c4b760c842433cb58339a0fafef3db"
	}
}

Returns transaction id or error code.

tx_status

Checks status of existing transaction. Status can be Pending(0), InProgress(1), Cancelled(2), Completed(3), Failed(4), Registering(5). More info here TX statuses description.

-->

{
	"jsonrpc":"2.0", 
	"id": 4,
	"method":"tx_status", 
	"params":
	{
		"txId" : "10c4b760c842433cb58339a0fafef3db" 
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 4,
	"result":
	{ 
		"txId" : "10c4b760c842433cb58339a0fafef3db",
		"comment": "",
		"fee": 0,
		"kernel": "0000000000000000000000000000000000000000000000000000000000000000",
		"receiver": "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67",
		"sender": "f287176bdd517e9c277778e4c012bf6a3e687dd614fc552a1ed22a3fee7d94f2",
		"status": 4,
                "status_string" : "Failed",
                "failure_reason" : "No inputs",
		"value": 12342342,
		"height" : 1055,
		"confirmations" : 3,
		"create_time" : 1551100217,
		"income" : false
	} 
}

height and confirmations will be absent if transaction isn't in chain.

tx_split

Creates a specific set of outputs with given set of values and session.

The session parameter is important in the following case:

Let's say you need to do a payout to a 1000 people, each with different amount. First you split the UTXOs you have using the 'split' method but then if you want to make another transaction you want to make sure these UTXOs are not used for any other payout. To do that you 'lock' them with the session id during split, and they will only be spent of the specific session id is provided in the 'send' method.

-->

{
	"jsonrpc":"2.0", 
	"id": 5,
	"method":"tx_split", 
	"params":
	{
		"coins" : [11, 12, 13, 50000000],
		"fee" : 3
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 5,
	"result":
	{
		"txId" : "10c4b760c842433cb58339a0fafef3db"
	}
}

coins and fee are in Groth

txId you can provide your own transaction ID.

wallet_status

Get current wallet status height/hash/available/...

-->

{
	"jsonrpc":"2.0", 
	"id": 6,
	"method":"wallet_status"
}

<--

{
	"jsonrpc":"2.0", 
	"id": 6,
	"result":
	{
	    "current_height" : 1055,
	    "current_state_hash" : "f287176bdd517e9c277778e4c012bf6a3e687dd614fc552a1ed22a3fee7d94f2",
	    "prev_state_hash" : "bd39333a66a8b7cb3804b5978d42312c841dbfa03a1c31fc2f0627eeed6e43f2",
	    "available": 100500,
	    "receiving": 123,
	    "sending": 0,
	    "maturing": 50,
	    "locked": 30,
	    "difficulty": 2.93914,
	}
}

available - a sum of available UTXOs you can spend
sending/receiving - a sum of UTXOs currently sending/receiving
maturing - a sum of UTXOs currently maturing
locked - not currently using, ignore it
difficulty - the latest blockchain PoW difficulty

get_utxo

Get list of all unlocked UTXOs.

To do a pagination use count/skip parameters:

count - number of UTXO to get, all the UTXO will be returned by default.

skip - number of UTXO to skip, default is 0.

-->

{
	"jsonrpc":"2.0", 
	"id": 6,
	"method":"get_utxo",
	"params" :
	{
		"count" : 10,
		"skip" : 0
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 6,
	"result":
	[
		{
			"amount": 100000000,
			"createTxId": "f1930fd8bd224c829616c5e15eca6552",
			"id": "1f5df08a420fd7d06e6f726d010000000000000005f5e100",
			"maturity": 138353,
			"session": 0,
			"spentTxId": "6e75cef454a840d184396fb449c8b98d",
			"status": 6,
			"status_string": "spent",
			"type": "norm"
		}
	]
}

type can be fees, mine, norm, chng, ...

status can be Unavailable (0), Available (1), Maturing (2), Outgoing (3), Incoming (4), Spent (6)

tx_list

Get all the transactions with specified status or height (means height when a transaction was registered in the chain, so it works with status Completed(3) only).

To do a pagination use count/skip parameters:

count - number of transactions to get, all the transactions will be returned by default.

skip - number of transactions to skip, default is 0.

-->

{
	"jsonrpc":"2.0", 
	"id": 8,
	"method":"tx_list",
	"params":
	{
		"filter" : 
		{
			"status":4,
			"height":1055,
		},
		"skip" : 0,
		"count" : 10
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 8,
	"result":
	[
		{ 
			"txId" : "10c4b760c842433cb58339a0fafef3db",
			"comment": "",
			"fee": 0,
			"kernel": "0000000000000000000000000000000000000000000000000000000000000000",
			"receiver": "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67",
			"sender": "f287176bdd517e9c277778e4c012bf6a3e687dd614fc552a1ed22a3fee7d94f2",
			"status": 4,
			"status_string" : "Failed",
			"failure_reason" : "No inputs",
			"value": 12342342,
			"height" : 1055,
			"confirmations" : 0,
			"create_time" : 1551100217,
			"income" : false
		},
		{ 
			"txId" : "10c4b760c842433cb58339a0fafef3db",
			"comment": "",
			"fee": 0,
			"kernel": "0000000000000000000000000000000000000000000000000000000000000000",
			"receiver": "472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67",
			"sender": "f287176bdd517e9c277778e4c012bf6a3e687dd614fc552a1ed22a3fee7d94f2",
			"status": 4,
			"status_string" : "Failed",
			"failure_reason" : "No inputs",
			"value": 12342342,
			"height" : 1055,
			"confirmations" : 2,
			"create_time" : 1551100217,
			"income" : false
		}
	]
}

TX statuses description

Pending (0)     - initial state, a transaction is created, but not sent nowhere
InProgress (1)  - "Waiting for Sender/Waiting for Receiver" - to indicate that sender or receiver should come online to initiate the transaction
Canceled (2)    - "Cancelled" (by Sender, due to Rollback)
Completed (3)   - a transaction is completed
Failed (4)      - failed for some reason
Registering (5) - a transaction is taken care by the blockchain, some miner needs to PoW and to add it to a block, the block should be added to the blockchain

status_string is a string representation of status parameter.

height and confirmations will be absent if a transaction isn't in chain.

tx_cancel

Cancels running transaction, return true if successfully canceled or error with the reason.

-->

{
	"jsonrpc":"2.0", 
	"id": 4,
	"method":"tx_cancel", 
	"params":
	{
		"txId" : "a13525181c0d45b0a4c5c1a697c8a7b8"
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 4,
	"result": true
}

generate_tx_id

Generates ID for a transaction.

-->

{
	"jsonrpc":"2.0", 
	"id": 2,
	"method":"generate_tx_id"
}

<--

{
	"jsonrpc":"2.0", 
	"id": 2,
	"result":"10c4b760c842433cb58339a0fafef3db"
}

export_payment_proof

Exports payment proof for given txId.

-->

{
	"jsonrpc":"2.0", 
	"id": 4,
	"method":"export_payment_proof", 
	"params":
	{
		"txId" : "a13525181c0d45b0a4c5c1a697c8a7b8"
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 4,
	"result": 
        {
            "payment_proof": "8009f28991ef543253c8b6a2caf15cf99e23fb9c2b4ca30dc463c8ceb354d7979e80ef7d4255dd5e885200648abe5826d8e0ba0157d3e8cf9c42dcc8258b036986e50400371789ee82afc25ee29c9c57bcb1018b725a3a94c0ceb1fa7984ea13de4982553e0d78d925a362982182a971e654857b8e407e7ad2e9cb72b2b8228812f8ec50435351000c94e2c85996e9527d9b0c90a1843205a7ec8f99fa534083e5f1d055d9f53894"
        }

payment_proof is a hex-encoded byte buffer which contains information about sender, receiver, amount and kernel, signed with receiver's private key. This info could be unpacked and verified using verify_payment_proof method by the third party. Receiver creates a payment proof in order give receiver an ability to proof that actual payment was made. Sender does not sign transaction if receiver does not provide him this evidence.

verify_payment_proof

Verifies the payment_proof.

-->

{
	"jsonrpc":"2.0", 
	"id": 4,
	"method":"verify_payment_proof", 
	"params":
	{
		"payment_proof" : "8009f28991ef543253c8b6a2caf15cf99e23fb9c2b4ca30dc463c8ceb354d7979e80ef7d4255dd5e885200648abe5826d8e0ba0157d3e8cf9c42dcc8258b036986e50400371789ee82afc25ee29c9c57bcb1018b725a3a94c0ceb1fa7984ea13de4982553e0d78d925a362982182a971e654857b8e407e7ad2e9cb72b2b8228812f8ec50435351000c94e2c85996e9527d9b0c90a1843205a7ec8f99fa534083e5f1d055d9f53894"
	}
}

<--

{
	"jsonrpc":"2.0", 
	"id": 4,
	"result": 
        {
            "is_valid": true,
            "sender":   "9f28991ef543253c8b6a2caf15cf99e23fb9c2b4ca30dc463c8ceb354d7979e",
            "receiver": "ef7d4255dd5e885200648abe5826d8e0ba0157d3e8cf9c42dcc8258b036986e5",
            "amount":   2300000000,
            "kernel":   "ee82afc25ee29c9c57bcb1018b725a3a94c0ceb1fa7984ea13de4982553e0d78"
        }

is_valid is true if signature is valid, sender is a sender's SBBS address receiver is a receiver's SBBS address, is it is used to verify the signature amount amount sent by this transaction in Groth kernel id of the kernel of this transaction

IP whitelistening

Add --ip_whitelist=192.168.0.1,192.168.0.2 parameter to enable access to the API by IP address.

User authorization

The API methods can have access rights if you enable Access Control List (ACL) in the command line using --use_acl=1 parameter)

create_address      - write access
validate_address    - read access
addr_list           - read access
delete_address      - write access
edit_address        - write access
tx_send             - write access
tx_status           - read access
tx_split            - write access
tx_cancel           - write access
get_utxo            - read access
tx_list             - read access
wallet_status       - read access
generate_tx_id      - read access
export_payment_proof- read access
verify_payment_proof- read access

ACL file should look like a list with the access keys and read/write rights:

472e17b0419055ffee3b3813b98ae671579b0ac0dcd6f1a23b11a75ab148cc67 : write
bd39333a66a8b7cb3804b5978d42312c841dbfa03a1c31fc2f0627eeed6e43f2 : read
f287176bdd517e9c277778e4c012bf6a3e687dd614fc552a1ed22a3fee7d94f2 : read

Also, don't forget to send a user key in every JSONRPC request to the API now:

{"jsonrpc":"2.0","id":1,"method":"wallet_status","key":"bd39333a66a8b7cb3804b5978d42312c841dbfa03a1c31fc2f0627eeed6e43f2"}

TLS encryption

Add --use_tls=1 to enable TLS encryption. Also, you have to buy the certificates or create self signed certificates on your local machine and pass them using --tls_cert and --tls_key parameters.