Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into release/v1.8.0
Browse files Browse the repository at this point in the history
  • Loading branch information
briancorbin committed May 28, 2022
2 parents b402b43 + c0ff4c1 commit 5c31f00
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Create New Subaddress Request

## Parameters

| Required Param | Purpose | Requirements |
| :--- | :--- | :--- |
| `account_id` | The account on which to perform this action. | Account must exist in the wallet as a view only account. |
| `num_subaddresses_to_generate` | The number of desired subaddress. | |

## Example

{% tabs %}
{% tab title="Request" %}
```
Expand All @@ -20,7 +29,8 @@
{
"method": "create_new_subaddresses_request",
"result": {
"next_subaddress_index": "2",
"account_id": "f85920dd83f69d8850799e28240e3d395f0ad46dec2561b71f4614dd90a3edb5",
"next_subaddress_index": "10",
"num_subaddresses_to_generate": "10"
},
"jsonrpc": "2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Import Subaddresses

## Parameters

| Required Param | Purpose | Requirements |
| :--- | :--- | :--- |
| `account_id` | The account on which to perform this action. | Account must exist in the wallet as a view only account. |
| `subaddresses` | List of subaddress in json format | |

### subaddress import json fields:
| field | description (all strings) |
| :--- | :--- |
| `object` | "view_only_subaddress" |
| `public_address` |A b58 encoding of the public address materials |
| `account_id` | The account that owns this subaddress |
| `comment` | Additional data associated with this address. |
| `subaddress_index` | The index of this address in the subaddress space for the account |
| `public_spend_key` | The public spend key for this addres |

## Example

{% tabs %}
{% tab title="Request" %}
```
{
"method": "import_subaddresses_to_view_only_account",
"params": {
"account_id": "f85920dd83f69d8850799e28240e3d395f0ad46dec2561b71f4614dd90a3edb5",
"subaddresses": "[{
object: "view_only_subaddress",
public_address: "USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z",
account_id: "f85920dd83f69d8850799e28240e3d395f0ad46dec2561b71f4614dd90a3edb5",
comment: "target address",
"subaddress_index: "5",
public_spend_key: "asdsfpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z"
}]"
},
"jsonrpc": "2.0",
"id": 1
}
```
{% endtab %}

{% tab title="Response" %}
```
{
"method": "import_subaddresses_to_view_only_account",
"result": {
"public_address_b58s": "["USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z"]",
},
"jsonrpc": "2.0",
"id": 1
}
```
{% endtab %}
{% endtabs %}
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Create Account Sync Request

## Parameters

| Required Param | Purpose | Requirements |
| :--- | :--- | :--- |
| `account_id` | The account on which to perform this action. | Account must exist in the wallet as a view only account. |

{% tabs %}
{% tab title="Request" %}
```
Expand Down
55 changes: 55 additions & 0 deletions docs/view-only-accounts/syncing/sync_view_only_account.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Sync View Only Account

## Parameters

| Required Param | Purpose | Requirements |
| :--- | :--- | :--- |
| `account_id` | The account on which to perform this action. | Account must exist in the wallet as a view only account. |
| `completed_txos` | signed txos. A array of tuples (txoID, KeyImage) | |
| `subaddresses` | The subaddress to sync | |

### subaddress import json fields:
| field | description (all strings) |
| :--- | :--- |
| `object` | "view_only_subaddress" |
| `public_address` |A b58 encoding of the public address materials |
| `account_id` | The account that owns this subaddress |
| `comment` | Additional data associated with this address. |
| `subaddress_index` | The index of this address in the subaddress space for the account |
| `public_spend_key` | The public spend key for this addres |

## Example

{% tabs %}
{% tab title="Request" %}
```
{
"method": "sync_view_only_account",
"params": {
"account_id": "f85920dd83f69d8850799e28240e3d395f0ad46dec2561b71f4614dd90a3edb5",
"completed_txos": "[(asdasedeerwe..., sadjashdoauihdkahwk...)]",
"subaddresses": "[{
object: "view_only_subaddress",
public_address: "USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z",
account_id: "f85920dd83f69d8850799e28240e3d395f0ad46dec2561b71f4614dd90a3edb5",
comment: "target address",
"subaddress_index: "5",
public_spend_key: "asdsfpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z"
}]"
},
"jsonrpc": "2.0",
"id": 1
}
```
{% endtab %}

{% tab title="Response" %}
```
{
"method": "sync_view_only_account",
"jsonrpc": "2.0",
"id": 1
}
```
{% endtab %}
{% endtabs %}
210 changes: 209 additions & 1 deletion full-service/src/json_rpc/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ mod e2e {
dispatch_with_header_expect_error, setup, setup_with_api_key,
},
test_utils::{
add_block_to_ledger_db, add_block_with_tx_proposal, manually_sync_account, MOB,
add_block_to_ledger_db, add_block_with_tx_proposal, manually_sync_account,
manually_sync_view_only_account, MOB,
},
util::b58::b58_decode_public_address,
};
Expand Down Expand Up @@ -3778,4 +3779,211 @@ mod e2e {

dispatch_with_header_expect_error(&client, body, header, &logger, Status::Unauthorized);
}

#[test_with_logger]
fn test_e2e_view_only_account_flow(logger: Logger) {
// create normal account
let mut rng: StdRng = SeedableRng::from_seed([20u8; 32]);
let (client, mut ledger_db, db_ctx, _network_state) = setup(&mut rng, logger.clone());
let wallet_db = db_ctx.get_db_instance(logger.clone());

// Create Account
let body = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "create_account",
"params": {
"name": "Alice Main Account",
},
});
let res = dispatch(&client, body, &logger);
assert_eq!(res.get("jsonrpc").unwrap(), "2.0");

let result = res.get("result").unwrap();
let account_obj = result.get("account").unwrap();
assert!(account_obj.get("account_id").is_some());
assert_eq!(account_obj.get("name").unwrap(), "Alice Main Account");
let account_id = account_obj.get("account_id").unwrap();
let main_address = account_obj.get("main_address").unwrap().as_str().unwrap();
let main_account_address = b58_decode_public_address(main_address).unwrap();

// add some funds to that account
add_block_to_ledger_db(
&mut ledger_db,
&vec![main_account_address],
100 * MOB,
&vec![KeyImage::from(rng.next_u64())],
&mut rng,
);
manually_sync_account(
&ledger_db,
&db_ctx.get_db_instance(logger.clone()),
&AccountID(account_id.as_str().unwrap().to_string()),
&logger,
);

// confirm that the regular account has the correct balance
let body = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "get_balance_for_account",
"params": {
"account_id": account_id,
},
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let balance_status = result.get("balance").unwrap();
let unspent = balance_status["unspent_pmob"].as_str().unwrap();
assert_eq!(unspent, "100000000000000");

// export view only import package
let body = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "export_view_only_account_package",
"params": {
"account_id": account_id,
},
});
let res = dispatch(&client, body, &logger);
assert_eq!(res.get("jsonrpc").unwrap(), "2.0");
let result = res.get("result").unwrap();
let request = result.get("json_rpc_request").unwrap();

// remove regular account (can't have both view only and regular in same wallet)
let body = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "remove_account",
"params": {
"account_id": account_id,
}
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
assert_eq!(result["removed"].as_bool().unwrap(), true);

// import vo account
let body = json!(request);
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let account = result.get("view_only_account").unwrap();
let vo_account_id = account.get("account_id").unwrap();
assert_eq!(vo_account_id, account_id);

// sync the view only account
manually_sync_view_only_account(
&ledger_db,
&wallet_db,
vo_account_id.as_str().unwrap(),
&logger,
);

// check balance for view only account
let body = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "get_balance_for_view_only_account",
"params": {
"account_id": account_id,
},
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let balance_status = result.get("balance").unwrap();
let unspent = balance_status["unspent_pmob"].as_str().unwrap();
assert_eq!(unspent, "100000000000000");

// test get
let body = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "get_view_only_account",
"params": {
"account_id": account_id,
}
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let account = result.get("view_only_account").unwrap();
let vo_account_id = account.get("account_id").unwrap();
assert_eq!(vo_account_id, account_id);

// test update name
let name = "Look at these coins";
let body = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "update_view_only_account_name",
"params": {
"account_id": account_id,
"name": name,
}
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let account = result.get("view_only_account").unwrap();
let account_name = account.get("name").unwrap();
assert_eq!(name, account_name);

// create new subaddress request
let body = json!({
"jsonrpc": "2.0",
"id": 1,
"method": "create_new_subaddresses_request",
"params": {
"account_id": account_id,
"num_subaddresses_to_generate": "2",
},
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let next_index = result
.get("next_subaddress_index")
.unwrap()
.as_str()
.unwrap();
assert_eq!(next_index, "2");

// test creating unsigned tx
let body = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "build_unsigned_transaction",
"params": {
"account_id": account_id,
"recipient_public_address": main_address,
"value_pmob": "50000000000000",
}
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let _tx = result.get("unsigned_tx").unwrap();

// test remove
let body = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "remove_view_only_account",
"params": {
"account_id": account_id,
}
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let removed = result.get("removed").unwrap().as_bool().unwrap();
assert!(removed);

// test get-all
let body = json!({
"jsonrpc": "2.0",
"id": 2,
"method": "get_all_view_only_accounts",
});
let res = dispatch(&client, body, &logger);
let result = res.get("result").unwrap();
let account_ids = result.get("account_ids").unwrap().as_array().unwrap();
assert_eq!(account_ids.len(), 0);
}
}
9 changes: 5 additions & 4 deletions full-service/src/service/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,16 @@ where

let mut min_synced_block_index = network_block_height - 1;
let mut account_ids = Vec::new();

for account in accounts {
let account_id = AccountID(account.account_id_hex.clone());
let balance = Self::get_balance_inner(&account_id.to_string(), None, &conn)?;
account_map.insert(account_id.clone(), account.clone());
unspent += balance.0;
pending += balance.1;
spent += balance.2;
secreted += balance.3;
orphaned += balance.4;
pending += balance.2;
spent += balance.3;
secreted += balance.4;
orphaned += balance.5;

// account.next_block_index is an index in range [0..ledger_db.num_blocks()]
min_synced_block_index = std::cmp::min(
Expand Down

0 comments on commit 5c31f00

Please sign in to comment.