Task: BCH/SLP Activation
task::enable_bch::init
Use this method for task managed activation of BCH and SLP tokens. Refer to the task managed activation overview for activation of other coin types.
Arguments
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticker | string | ✓ | Ticker of the platform protocol coin. Options: BCH or tBCH | |
| bchd_urls | array of strings | ✓ | A list of BCHD gRPC API server URLs, used for validation of SLP token transactions. It's recommended to add as many servers as possible. The URLs list can be found at https://bchd.fountainhead.cash/. | |
| mode | object | ✓ | A standard ActivationMode object. | |
| tx_history | boolean | – | false | If true, spawns a background loop to store the local cache of address(es) transactions. |
| slp_tokens_requests | array of objects | ✓ | A list of standard TokensRequest objects. | |
| address_format | object | – | Overwrites the address format from coins file, if set. A standard AddressFormat object. | |
| allow_slp_unsafe_conf | boolean | – | false | If true, allows bchd_urls to be empty. Warning: it is highly unsafe to do so as it may lead to invalid SLP transactions generation and tokens burning. |
| get_balances | boolean | – | true | If false, coin and token balances will not be returned in the response, and the response will be returned more quickly. |
| required_confirmations | integer | – | value in the coins file, or 3 if not set | Confirmations to wait for steps in swap. |
| requires_notarization | boolean | – | true | Has no effect on BCH. |
| tx_history | boolean | – | true | If true the Komodo DeFi Framework API will preload transaction history as a background process. Must be set to true to use the my_tx_history method |
| utxo_merge_params | object | ✓ | A standard UtxoMergeParams object. Used to reduce a wallet's UTXO count in cases where it is causing significantly slower RPC responses. |
Response
| Parameter | Type | Required | Description |
|---|---|---|---|
| task_id | integer | ✓ | An identifying number which is used to query task status. |
📌 Examples
Activation in Trezor mode
POST task::enable_bch::init
{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::init",
"params": {
"ticker": "BCH",
"activation_params": {
"bchd_urls": [
"https://bchd.dragonhound.info"
],
"mode": {
"rpc": "Electrum",
"rpc_data": {
"servers": [
{
"url": "bch.electrum3.cipig.net:10055",
"protocol": "TCP"
},
{
"url": "bch.electrum3.cipig.net:20055",
"protocol": "SSL"
},
{
"url": "bch.electrum3.cipig.net:30055",
"protocol": "WSS"
}
]
}
},
"slp_tokens_requests": [
{
"ticker": "USDF"
},
{
"ticker": "ASLP-SLP",
"required_confirmations": 3
}
],
"tx_history": true,
"required_confirmations": 5,
"requires_notarization": false,
"address_format": {
"format": "cashaddress",
"network": "bitcoincash"
},
"utxo_merge_params": {
"merge_at": 50,
"check_every": 10,
"max_merge_at_once": 25
}
}
}
} curl --url "http://127.0.0.1:7783" --data '{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::init",
"params": {
"ticker": "BCH",
"activation_params": {
"bchd_urls": [
"https://bchd.dragonhound.info"
],
"mode": {
"rpc": "Electrum",
"rpc_data": {
"servers": [
{
"url": "bch.electrum3.cipig.net:10055",
"protocol": "TCP"
},
{
"url": "bch.electrum3.cipig.net:20055",
"protocol": "SSL"
},
{
"url": "bch.electrum3.cipig.net:30055",
"protocol": "WSS"
}
]
}
},
"slp_tokens_requests": [
{
"ticker": "USDF"
},
{
"ticker": "ASLP-SLP",
"required_confirmations": 3
}
],
"tx_history": true,
"required_confirmations": 5,
"requires_notarization": false,
"address_format": {
"format": "cashaddress",
"network": "bitcoincash"
},
"utxo_merge_params": {
"merge_at": 50,
"check_every": 10,
"max_merge_at_once": 25
}
}
}
}' import requests
import json
url = "http://127.0.0.1:7783"
payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::init",
"params": {
"ticker": "BCH",
"activation_params": {
"bchd_urls": [
"https://bchd.dragonhound.info"
],
"mode": {
"rpc": "Electrum",
"rpc_data": {
"servers": [
{
"url": "bch.electrum3.cipig.net:10055",
"protocol": "TCP"
},
{
"url": "bch.electrum3.cipig.net:20055",
"protocol": "SSL"
},
{
"url": "bch.electrum3.cipig.net:30055",
"protocol": "WSS"
}
]
}
},
"slp_tokens_requests": [
{
"ticker": "USDF"
},
{
"ticker": "ASLP-SLP",
"required_confirmations": 3
}
],
"tx_history": true,
"required_confirmations": 5,
"requires_notarization": false,
"address_format": {
"format": "cashaddress",
"network": "bitcoincash"
},
"utxo_merge_params": {
"merge_at": 50,
"check_every": 10,
"max_merge_at_once": 25
}
}
}
}
response = requests.post(url, json=payload)
print(json.dumps(response.json(), indent=2)) const payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::init",
"params": {
"ticker": "BCH",
"activation_params": {
"bchd_urls": [
"https://bchd.dragonhound.info"
],
"mode": {
"rpc": "Electrum",
"rpc_data": {
"servers": [
{
"url": "bch.electrum3.cipig.net:10055",
"protocol": "TCP"
},
{
"url": "bch.electrum3.cipig.net:20055",
"protocol": "SSL"
},
{
"url": "bch.electrum3.cipig.net:30055",
"protocol": "WSS"
}
]
}
},
"slp_tokens_requests": [
{
"ticker": "USDF"
},
{
"ticker": "ASLP-SLP",
"required_confirmations": 3
}
],
"tx_history": true,
"required_confirmations": 5,
"requires_notarization": false,
"address_format": {
"format": "cashaddress",
"network": "bitcoincash"
},
"utxo_merge_params": {
"merge_at": 50,
"check_every": 10,
"max_merge_at_once": 25
}
}
}
};
const response = await fetch("http://127.0.0.1:7783", {
method: "POST",
body: JSON.stringify(payload),
});
console.log(await response.json()); <?php
$payload = <<<'JSON'
{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::init",
"params": {
"ticker": "BCH",
"activation_params": {
"bchd_urls": [
"https://bchd.dragonhound.info"
],
"mode": {
"rpc": "Electrum",
"rpc_data": {
"servers": [
{
"url": "bch.electrum3.cipig.net:10055",
"protocol": "TCP"
},
{
"url": "bch.electrum3.cipig.net:20055",
"protocol": "SSL"
},
{
"url": "bch.electrum3.cipig.net:30055",
"protocol": "WSS"
}
]
}
},
"slp_tokens_requests": [
{
"ticker": "USDF"
},
{
"ticker": "ASLP-SLP",
"required_confirmations": 3
}
],
"tx_history": true,
"required_confirmations": 5,
"requires_notarization": false,
"address_format": {
"format": "cashaddress",
"network": "bitcoincash"
},
"utxo_merge_params": {
"merge_at": 50,
"check_every": 10,
"max_merge_at_once": 25
}
}
}
}
JSON;
$ch = curl_init("http://127.0.0.1:7783");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response; package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
payload := []byte(`{"userpass":"RPC_UserP@SSW0RD","mmrpc":"2.0","method":"task::enable_bch::init","params":{"ticker":"BCH","activation_params":{"bchd_urls":["https://bchd.dragonhound.info"],"mode":{"rpc":"Electrum","rpc_data":{"servers":[{"url":"bch.electrum3.cipig.net:10055","protocol":"TCP"},{"url":"bch.electrum3.cipig.net:20055","protocol":"SSL"},{"url":"bch.electrum3.cipig.net:30055","protocol":"WSS"}]}},"slp_tokens_requests":[{"ticker":"USDF"},{"ticker":"ASLP-SLP","required_confirmations":3}],"tx_history":true,"required_confirmations":5,"requires_notarization":false,"address_format":{"format":"cashaddress","network":"bitcoincash"},"utxo_merge_params":{"merge_at":50,"check_every":10,"max_merge_at_once":25}}}}`)
resp, err := http.Post("http://127.0.0.1:7783", "application/json", bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
} require 'net/http'
require 'json'
require 'uri'
uri = URI("http://127.0.0.1:7783")
payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::init",
"params": {
"ticker": "BCH",
"activation_params": {
"bchd_urls": [
"https://bchd.dragonhound.info"
],
"mode": {
"rpc": "Electrum",
"rpc_data": {
"servers": [
{
"url": "bch.electrum3.cipig.net:10055",
"protocol": "TCP"
},
{
"url": "bch.electrum3.cipig.net:20055",
"protocol": "SSL"
},
{
"url": "bch.electrum3.cipig.net:30055",
"protocol": "WSS"
}
]
}
},
"slp_tokens_requests": [
{
"ticker": "USDF"
},
{
"ticker": "ASLP-SLP",
"required_confirmations": 3
}
],
"tx_history": true,
"required_confirmations": 5,
"requires_notarization": false,
"address_format": {
"format": "cashaddress",
"network": "bitcoincash"
},
"utxo_merge_params": {
"merge_at": 50,
"check_every": 10,
"max_merge_at_once": 25
}
}
}
}
response = Net::HTTP.post(uri, payload.to_json, 'Content-Type' => 'application/json')
puts JSON.pretty_generate(JSON.parse(response.body)) Show Response
Response
{
"mmrpc": "2.0",
"result": {
"task_id": 1
},
"id": null
} task::enable_bch::status
After running the task::enable_bch::init method, we can query the status of activation to check its progress.
The response will return the following:
- Result of the task (success or error)
- Progress status (what state the task is in)
- Required user action (what user should do before the task can continue)
Arguments
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| task_id | integer | ✓ | The identifying number returned when initiating the initialisation process. | |
| forget_if_finished | boolean | – | true | If false, will return final response for completed tasks. |
Command
POST task::enable_bch::status
{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::status",
"params": {
"task_id": 0,
"forget_if_finished": false
}
} curl --url "http://127.0.0.1:7783" --data '{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::status",
"params": {
"task_id": 0,
"forget_if_finished": false
}
}' import requests
import json
url = "http://127.0.0.1:7783"
payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::status",
"params": {
"task_id": 0,
"forget_if_finished": false
}
}
response = requests.post(url, json=payload)
print(json.dumps(response.json(), indent=2)) const payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::status",
"params": {
"task_id": 0,
"forget_if_finished": false
}
};
const response = await fetch("http://127.0.0.1:7783", {
method: "POST",
body: JSON.stringify(payload),
});
console.log(await response.json()); <?php
$payload = <<<'JSON'
{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::status",
"params": {
"task_id": 0,
"forget_if_finished": false
}
}
JSON;
$ch = curl_init("http://127.0.0.1:7783");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response; package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
payload := []byte(`{"userpass":"RPC_UserP@SSW0RD","mmrpc":"2.0","method":"task::enable_bch::status","params":{"task_id":0,"forget_if_finished":false}}`)
resp, err := http.Post("http://127.0.0.1:7783", "application/json", bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
} require 'net/http'
require 'json'
require 'uri'
uri = URI("http://127.0.0.1:7783")
payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::status",
"params": {
"task_id": 0,
"forget_if_finished": false
}
}
response = Net::HTTP.post(uri, payload.to_json, 'Content-Type' => 'application/json')
puts JSON.pretty_generate(JSON.parse(response.body)) | Parameter | Type | Required | Description |
|---|---|---|---|
| status | string | ✓ | A short indication of how the enabling is progressing. |
| details | object | ✓ | Depending on the state of enabling progress, this will contain different information as shown in the responses below. |
Possible status values while activation is in progress:
ActivatingCoin: The first step of activation. It does not require any action from the user.RequestingWalletBalance: The first step of activation, while initial balances info is being requested. It does not require any action from the user.Finishing: Activation process completedWaitingForTrezorToConnect: Waiting for the user to plugin a Trezor deviceFollowHwDeviceInstructions: Waiting for the user to follow the instructions on the device
Once complete, status will be Ok, and the details object will have the following structure:
Response (ready, successful, HD mode)
| Parameter | Type | Description |
|---|---|---|
| current_block | integer | Block height of the coin being activated |
| ticker | string | Ticker of the coin being activated. |
| wallet_balance | object | A standard WalletBalanceInfo object. Note: the structure may vary based on the get_balances parameter value in the activation request. |
Show Response
{
"mmrpc": "2.0",
"result": {
"status": "Ok",
"details": {
"ticker": "BCH",
"current_block": 895348,
"wallet_balance": {
"wallet_type": "HD",
"accounts": [
{
"account_index": 0,
"derivation_path": "m/44'/145'/0'",
"total_balance": {
"BCH": {
"spendable": "0",
"unspendable": "0"
}
},
"addresses": [
{
"address": "bitcoincash:qq6qvc33strtjwnfktdqswwvxuhrhs2ussavvhv3a0",
"derivation_path": "m/44'/145'/0'/0/0",
"chain": "External",
"balance": {
"BCH": {
"spendable": "0",
"unspendable": "0"
}
}
}
]
}
]
}
}
},
"id": null
} Response (ready, successful, Iguana mode)
| Parameter | Type | Description |
|---|---|---|
| current_block | integer | Block height of the coin being activated |
| ticker | string | Ticker of the coin being activated. |
| wallet_balance | object | A standard WalletBalanceInfo object. Note: the structure may vary based on the get_balances parameter value in the activation request. |
Show Response
Response (in progress)
Show Response
{
"mmrpc": "2.0",
"result": {
"status": "InProgress",
"details": "RequestingWalletBalance"
},
"id": null
} Response (ready, error)
| Parameter | Type | Description |
|---|---|---|
| status | string | A short indication of how the requested process is progressing. |
| details.result | object | Depending on the state of process progress, this will contain different information as detailed in the items below. |
| .error | string | The ticker of the coin being activated |
| .error_path | string | Used for debugging. A reference to the function in code base which returned the error |
| .error_trace | string | Used for debugging. A trace of lines of code which led to the returned error |
| .error_type | string | An enumerated error identifier to indicate the category of error |
| .error_data | string | Additonal context for the error type |
Possible Error Cases:
TaskTimedOut- Timed out waiting for coin activation, connecting to the device trezor or for user to confirm pubkey)CoinCreationError- Error during activation. E.g. incorrect or inactive electrum servers.HwError- This is the most important error type. Unlike other error types,HwErrorrequires the GUI / User to check the details inerror_datafield to know which action is required. View the HwError error type details for more info.
task::enable_bch::user_action
If the task::enable_bch::status returns UserActionRequired, we need to use the task::enable_bch::user_action method to enter our PIN
Arguments
| Parameter | Type | Description |
|---|---|---|
| task_id | integer | The identifying number returned when initiating the initialisation process. |
| user_action | object | Object containing the params below |
| user_action.action_type | string | Will be TrezorPin for this method |
| user_action.pin | string (number) | When the Trezor device is displaying a grid of numbers for PIN entry, this param will contain your Trezor pin, as mapped through your keyboard numpad. See the image below for more information. |
Response
| Parameter | Type | Description |
|---|---|---|
| result | string | The outcome of the request. |
📌 Examples
Command
POST task::enable_bch::user_action
{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::user_action",
"params": {
"task_id": 0,
"user_action": {
"action_type": "TrezorPin",
"pin": "862743"
}
}
} curl --url "http://127.0.0.1:7783" --data '{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::user_action",
"params": {
"task_id": 0,
"user_action": {
"action_type": "TrezorPin",
"pin": "862743"
}
}
}' import requests
import json
url = "http://127.0.0.1:7783"
payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::user_action",
"params": {
"task_id": 0,
"user_action": {
"action_type": "TrezorPin",
"pin": "862743"
}
}
}
response = requests.post(url, json=payload)
print(json.dumps(response.json(), indent=2)) const payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::user_action",
"params": {
"task_id": 0,
"user_action": {
"action_type": "TrezorPin",
"pin": "862743"
}
}
};
const response = await fetch("http://127.0.0.1:7783", {
method: "POST",
body: JSON.stringify(payload),
});
console.log(await response.json()); <?php
$payload = <<<'JSON'
{
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::user_action",
"params": {
"task_id": 0,
"user_action": {
"action_type": "TrezorPin",
"pin": "862743"
}
}
}
JSON;
$ch = curl_init("http://127.0.0.1:7783");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response; package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
payload := []byte(`{"userpass":"RPC_UserP@SSW0RD","mmrpc":"2.0","method":"task::enable_bch::user_action","params":{"task_id":0,"user_action":{"action_type":"TrezorPin","pin":"862743"}}}`)
resp, err := http.Post("http://127.0.0.1:7783", "application/json", bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
} require 'net/http'
require 'json'
require 'uri'
uri = URI("http://127.0.0.1:7783")
payload = {
"userpass": "RPC_UserP@SSW0RD",
"mmrpc": "2.0",
"method": "task::enable_bch::user_action",
"params": {
"task_id": 0,
"user_action": {
"action_type": "TrezorPin",
"pin": "862743"
}
}
}
response = Net::HTTP.post(uri, payload.to_json, 'Content-Type' => 'application/json')
puts JSON.pretty_generate(JSON.parse(response.body)) Show Response
Response (success)
{
"mmrpc": "2.0",
"result": "success",
"id": null
} task::enable_bch::cancel
If you want to cancel the enabling process before it has completed, you can use this method.
Arguments
| Structure | Type | Description |
|---|---|---|
| task_id | integer | The identifying number returned when initiating the enabling process. |
Response
| Structure | Type | Description |
|---|---|---|
| result | string | Indicates task cancellation was succesful. |
| error | string | An error message to explain what went wrong. |
| error_path | string | An indicator of the class or function which reurned the error. |
| error_trace | string | An indicator of where in the source code the error was thrown. |
| error_type | string | An enumerated value for the returned error. |
| error_data | string | The input task ID which resulted in the error. |
POST task::enable_bch::cancel
{
"userpass": "RPC_UserP@SSW0RD",
"method": "task::enable_bch::cancel",
"mmrpc": "2.0",
"params": {
"task_id": 3
}
} curl --url "http://127.0.0.1:7783" --data '{
"userpass": "RPC_UserP@SSW0RD",
"method": "task::enable_bch::cancel",
"mmrpc": "2.0",
"params": {
"task_id": 3
}
}' import requests
import json
url = "http://127.0.0.1:7783"
payload = {
"userpass": "RPC_UserP@SSW0RD",
"method": "task::enable_bch::cancel",
"mmrpc": "2.0",
"params": {
"task_id": 3
}
}
response = requests.post(url, json=payload)
print(json.dumps(response.json(), indent=2)) const payload = {
"userpass": "RPC_UserP@SSW0RD",
"method": "task::enable_bch::cancel",
"mmrpc": "2.0",
"params": {
"task_id": 3
}
};
const response = await fetch("http://127.0.0.1:7783", {
method: "POST",
body: JSON.stringify(payload),
});
console.log(await response.json()); <?php
$payload = <<<'JSON'
{
"userpass": "RPC_UserP@SSW0RD",
"method": "task::enable_bch::cancel",
"mmrpc": "2.0",
"params": {
"task_id": 3
}
}
JSON;
$ch = curl_init("http://127.0.0.1:7783");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = curl_exec($ch);
curl_close($ch);
echo $response; package main
import (
"bytes"
"fmt"
"io"
"net/http"
)
func main() {
payload := []byte(`{"userpass":"RPC_UserP@SSW0RD","method":"task::enable_bch::cancel","mmrpc":"2.0","params":{"task_id":3}}`)
resp, err := http.Post("http://127.0.0.1:7783", "application/json", bytes.NewBuffer(payload))
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
} require 'net/http'
require 'json'
require 'uri'
uri = URI("http://127.0.0.1:7783")
payload = {
"userpass": "RPC_UserP@SSW0RD",
"method": "task::enable_bch::cancel",
"mmrpc": "2.0",
"params": {
"task_id": 3
}
}
response = Net::HTTP.post(uri, payload.to_json, 'Content-Type' => 'application/json')
puts JSON.pretty_generate(JSON.parse(response.body)) Show Response
Response (success)
{
"mmrpc": "2.0",
"result": "success",
"id": null
} Show Error Responses
Response (success - already finished)
{
"mmrpc": "2.0",
"error": "Task is finished already",
"error_path": "init_standalone_coin.manager",
"error_trace": "init_standalone_coin:144] manager:101]",
"error_type": "TaskFinished",
"error_data": 0,
"id": null
}Response (error - no such task)
{
"mmrpc": "2.0",
"error": "No such task '1'",
"error_path": "init_standalone_coin",
"error_trace": "init_standalone_coin:119]",
"error_type": "NoSuchTask",
"error_data": 1,
"id": null
}