diff --git a/doc/src/wallet.md b/doc/src/wallet.md
index 37a154b99db41..9ab5ab71d0c4f 100644
--- a/doc/src/wallet.md
+++ b/doc/src/wallet.md
@@ -39,16 +39,17 @@ customized with additional accounts, objects, code, etc. as described
in [Genesis customization](#genesis-customization).
The network configuration is stored in `network.conf` and
-can be used subsequently to start the network. A `wallet.conf` is
+can be used subsequently to start the network. `wallet.conf` and `wallet.key` are
also created to be used by the Sui wallet to manage the
newly created accounts.
### View created accounts
-The genesis process creates a configuration file `wallet.conf` for the
+The genesis process creates a configuration file `wallet.conf`, and a keystore file `wallet.key` for the
Sui wallet. The config file contains information of the accounts and
-the Sui network. Sui wallet uses the network information to communicate
+the Sui network. The keystore file contains all the public-private key pair of the created accounts.
+Sui wallet uses the network information in `wallet.conf` to communicate
with the Sui network authorities and create transactions using the key
-pairs residing in the config file.
+pairs residing in the keystore file.
Here is an example of `wallet.conf` showing the accounts and key pairs
in the wallet configuration (with some values omitted):
@@ -57,8 +58,7 @@ in the wallet configuration (with some values omitted):
{
"accounts": [
{
- "address": "a4c0a493ce9879ea06bac93461810cf947823bb3",
- "key_pair": "MTpXG/yJq0OLOknghzYRCS6D/Rz+97gpR7hZhUCUNT5pMCy49v7hZkCSHm38e+cp+sdxLgTrSAuCbDxqkF1MTg=="
+ "address": "a4c0a493ce9879ea06bac93461810cf947823bb3"
},
...
],
@@ -79,25 +79,27 @@ in the wallet configuration (with some values omitted):
"nanos": 0
},
"buffer_size": 65507,
- "db_folder_path": "./client_db"
+ "db_folder_path": "./client_db",
+ "keystore": {
+ "File": "./wallet.key"
+ }
}
```
-The `accounts` variable contains all of the account's address and key pairs.
-This will be used by the wallet to sign transactions. The `authorities`
-variable contains Sui network authorities' name, host and port information.
+The `accounts` variable contains the account's address the wallet manages.
+The `authorities` variable contains Sui network authorities' name, host and port information.
It is used to establish connections to the Sui network.
Note `send_timeout`, `recv_timeout` and `buffer_size` are the network
parameters and `db_folder_path` is the path to the account's client state
-database. This database stores all of the transaction data, certificates
+database. This database stores all the transaction data, certificates
and object data belonging to the account.
#### Key management
-As you might have noticed, the key pairs are stored as plain text in `wallet.conf`,
-which is not secure and shouldn't be used in a production environment. We have plans to
+The key pairs are stored in `wallet.key`. However, this is not secure
+and shouldn't be used in a production environment. We have plans to
implement more secure key management and support hardware signing in a future release.
-:warning: **Do not use in production**: Keys are stored in plain text!
+:warning: **Do not use in production**: Keys are stored in file!
### Starting the network
@@ -203,17 +205,242 @@ Created new keypair for address : 3F8962C87474F8FB8BFB99151D5F83E677062078
#### Add existing accounts to `wallet.conf` manually.
-If you have existing key pair from an old wallet config, you can copy the account data manually to the new `wallet.conf`'s accounts section.
+If you have an existing key pair from an old wallet config, you can copy the account
+address manually to the new `wallet.conf`'s accounts section, and add the key pair to the keystore file;
+you won't be able to mutate objects if the account key is missing from the keystore.
-The account data looks like this:
+Restart the Sui wallet after the modification; the new accounts will appear in the wallet if you query the addresses.
+
+## View objects owned by the account
+You can use the `objects` command to view the objects owned by the address.
+
+`objects` command usage :
+
+```shell
+USAGE:
+ objects [FLAGS] --address
+
+FLAGS:
+ -h, --help Prints help information
+ --json Returns command outputs in JSON format
+ -V, --version Prints version information
+
+OPTIONS:
+ --address Address owning the objects
+```
+To view the objects owned by the accounts created in genesis, run the following command in the Sui interactive console (substitute the address with one of the genesis addresses in your wallet):
+```shell
+sui>-$ objects --address 0DC70EA8CA82FE6966900C697B73A235B8E2346F
+```
+The result should resemble the following, which shows the object in the format of (`object_id`, `sequence_number`, `object_hash`).
+```shell
+Showing 5 results.
+(0E4260A6AA1DF29790E76128DC094C030C2D1819, SequenceNumber(0), o#a4ab81b926bb51b64c33fd56fad24a5a33ea4ff8c244349a985c61c7d1a94570)
+(70B26102F9DE9A3CC6FF7CB085BA750DA16FDECE, SequenceNumber(0), o#0028abf5225bfcf0a3762996e7c6f54fa7fec00f0526b2ede51f592f49540c30)
+(8E306E956CF5C0F058F048A4A00C25BF90AE5A9B, SequenceNumber(0), o#5ae8e7feff1ad501d8ae96bd10fad846e51bd70d4000a284a65eb183b1a1e459)
+(9C7626A4CBFFCE894518B8A317F06D051597A378, SequenceNumber(0), o#10dd0b5cabf227952a6e731001d3b57039595225eb188ca6e7ac65bf55ac7c6f)
+(AFA6A58082E961E8706FFF48A0D531C2BED8A94D, SequenceNumber(0), o#2c4b5c7c8be3055287deb4d445c87cf02603d84155d761bcd71f0457d76254ad)
+```
+If you want to view more information about the objects, you can use the `object` command.
+
+Usage of `object` command :
+```shell
+USAGE:
+ object [FLAGS] --id
+
+FLAGS:
+ -h, --help Prints help information
+ --json Returns command outputs in JSON format
+ -V, --version Prints version information
+
+OPTIONS:
+ --id Object ID of the object to fetch
+```
+To view the object, use the following command:
+```bash
+object --id 0E4260A6AA1DF29790E76128DC094C030C2D1819
+```
+This should give you output similar to the following:
+```shell
+Owner: SingleOwner(k#ebcf32ca2998dc04b29dc6083250408278f96435)
+Version: 0
+ID: 0E4260A6AA1DF29790E76128DC094C030C2D1819
+Readonly: false
+Type: 0x2::Coin::Coin<0x2::GAS::GAS>
+```
+The result shows some basic information about the object, the owner,
+version, ID, if the object is immutable and the type of the object.
+If you need a deeper look into the object, you can use the `--json`
+flag to view the raw JSON representation of the object.
+Here is an example:
```json
- {
- "address": "a4c0a493ce9879ea06bac93461810cf947823bb3",
- "key_pair": "MTpXG/yJq0OLOknghzYRCS6D/Rz+97gpR7hZhUCUNT5pMCy49v7hZkCSHm38e+cp+sdxLgTrSAuCbDxqkF1MTg=="
- }
+{"contents":{"fields":{"id":{"fields":{"id":{"fields":{"id":{"fields":{"bytes":"0e4260a6aa1df29790e76128dc094c030c2d1819"},"type":"0x2::ID::ID"}},"type":"0x2::ID::UniqueID"},"version":0},"type":"0x2::ID::VersionedID"},"value":100000},"type":"0x2::Coin::Coin<0x2::GAS::GAS>"},"owner":{"SingleOwner":[235,207,50,202,41,152,220,4,178,157,198,8,50,80,64,130,120,249,100,53]},"tx_digest":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}
```
-Restart the Sui wallet after the modification; the new accounts will appear in the wallet if you query the addresses.
+
+## Transfer objects
+If you inspect a newly created account, you would expect the account does not own any object.
+```shell
+sui>-$ new-address
+Created new keypair for address : 830F66EA8EA867DDCA479535BC12CE2852E571F2
+sui>-$ objects --address 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Showing 0 results.
+```
+To add objects to the account, you can [invoke a move function](#calling-move-code),
+or you can transfer one of the existing objects from the genesis account to the new account.
+We will explore how to transfer objects using the wallet in this section.
+
+`transfer` command usage:
+```shell
+USAGE:
+ transfer [FLAGS] --gas --object-id --to
+
+FLAGS:
+ -h, --help Prints help information
+ --json Returns command outputs in JSON format
+ -V, --version Prints version information
+
+OPTIONS:
+ --gas ID of the gas object for gas payment, in 20 bytes Hex string
+ --object-id Object to transfer, in 20 bytes Hex string
+ --to Recipient address
+```
+To transfer an object to a recipient, you will need the recipient's address,
+the object ID of the object that you want to transfer,
+and the gas object' ID for the transaction fee payment.
+
+Here is an example transfer of an object to account `830F66EA8EA867DDCA479535BC12CE2852E571F2`.
+```shell
+sui>-$ transfer --to 830F66EA8EA867DDCA479535BC12CE2852E571F2 --object-id 1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE --gas 27073453E1B556D1B6C2E4BE94FF2A3928D788BF
+Transfer confirmed after 10500 us
+----- Certificate ----
+Signed Authorities : [k#a723959ed6c6d9b4a508fa527c00c215681812b2f0e86c486bbc204ca94f6df9, k#de9739d8d39bd1e9cfd11ab777fdce42ddf3fd862601f6ab09ee7482054e8da0, k#fb942f73e08b2686d0daef41307fd15804bfd953baf497762f36255401d7b2bf]
+Transaction Kind : Transfer
+Recipient : 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Object ID : 1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE
+Sequence Number : SequenceNumber(0)
+Object Digest : 9d0101cbc56fffae871896864910f6eab4d9af51884758d9e4582766314cce54
+----- Transaction Effects ----
+Status : Success { gas_used: 18 }
+Mutated Objects:
+1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE SequenceNumber(1) o#5e98374af72fa72f69f51b05eff1298b0f9045998f2d63db65ad1c26153bd5b3
+27073453E1B556D1B6C2E4BE94FF2A3928D788BF SequenceNumber(1) o#052a7e8af210c9be7409c5242e60d2d0e3f5f0e933e33b81280e4c5112923715
+```
+
+The account will now have 1 object
+```shell
+sui>-$ sync --address 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Client state sync complete.
+
+sui>-$ objects --address 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Showing 1 results.
+(1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, SequenceNumber(1), o#5e98374af72fa72f69f51b05eff1298b0f9045998f2d63db65ad1c26153bd5b3)
+```
+
+## Merging and splitting coin objects
+Overtime, the account might receive coins from other accounts and will become unmanageable when
+the number of coins grows; contrarily, the account might need to split the coins for payment or
+for transfer to another account.
+
+We can use the `merge-coin` command and `split-coin` command to consolidate or split coins, respectivly.
+
+### Merge coins
+Usage of `merge-coin`:
+```shell
+USAGE:
+ merge-coin [FLAGS] --coin-to-merge --gas --gas-budget --primary-coin
+
+FLAGS:
+ -h, --help Prints help information
+ --json Returns command outputs in JSON format
+ -V, --version Prints version information
+
+OPTIONS:
+ --coin-to-merge Coin to be merged, in 20 bytes Hex string
+ --gas ID of the gas object for gas payment, in 20 bytes Hex string
+ --gas-budget Gas budget for this call
+ --primary-coin Coin to merge into, in 20 bytes Hex string
+```
+Here is an example of how to merge coins. To merge coins, you will need at lease three coin objects -
+two coin objects for merging, and one for the gas payment.
+```shell
+sui>-$ objects --address 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Showing 3 results.
+(1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, SequenceNumber(1), o#5e98374af72fa72f69f51b05eff1298b0f9045998f2d63db65ad1c26153bd5b3)
+(6A506E6779CF5936145628C689045A25643ACBDC, SequenceNumber(1), o#6f66513613dc5e5f7814c79f6849850e2489628a94094e4e037e4e1397425a0d)
+(B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF, SequenceNumber(1), o#5e9289f55bac3508deaeca6d8ab4e9a4a43de5ef4f7d780a1a5a0a6633d85d96)
+
+sui>-$ merge-coin --primary-coin 1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE --coin-to-merge 6A506E6779CF5936145628C689045A25643ACBDC --gas B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF --gas-budget 1000
+----- Certificate ----
+Signed Authorities : [k#de9739d8d39bd1e9cfd11ab777fdce42ddf3fd862601f6ab09ee7482054e8da0, k#a723959ed6c6d9b4a508fa527c00c215681812b2f0e86c486bbc204ca94f6df9, k#fb942f73e08b2686d0daef41307fd15804bfd953baf497762f36255401d7b2bf]
+Transaction Kind : Call
+Gas Budget : 1000
+Package ID : 0x2
+Module : Coin
+Function : join
+Object Arguments : [(1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, SequenceNumber(1), o#5e98374af72fa72f69f51b05eff1298b0f9045998f2d63db65ad1c26153bd5b3), (6A506E6779CF5936145628C689045A25643ACBDC, SequenceNumber(1), o#6f66513613dc5e5f7814c79f6849850e2489628a94094e4e037e4e1397425a0d)]
+Pure Arguments : []
+Type Arguments : [Struct(StructTag { address: 0000000000000000000000000000000000000002, module: Identifier("GAS"), name: Identifier("GAS"), type_params: [] })]
+----- Merge Coin Results ----
+Updated Coin : Coin { id: 1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, value: 200000 }
+Updated Gas : Coin { id: B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF, value: 99996 }
+```
+
+### Split coins
+Usage of `split-coin`:
+```shell
+USAGE:
+ split-coin [FLAGS] [OPTIONS] --coin-id --gas --gas-budget
+
+FLAGS:
+ -h, --help Prints help information
+ --json Returns command outputs in JSON format
+ -V, --version Prints version information
+
+OPTIONS:
+ --amounts ... Amount to split out from the coin
+ --coin-id Coin to Split, in 20 bytes Hex string
+ --gas ID of the gas object for gas payment, in 20 bytes Hex string
+ --gas-budget Gas budget for this call
+```
+For splitting coins, you will need at lease two coins to execute the `split-coin` command,
+one coin to split, one for the gas payment.
+
+Here is an example of splitting coins, we are splitting out three new coins from the original coin,
+with values of 1000, 5000 and 3000 respectively; note that the `--amounts` argument accepts list of values.
+```shell
+sui>-$ objects --address 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Showing 2 results.
+(1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, SequenceNumber(2), o#1ce25191bf2832df1bda257044f5764c4ec6144dc6d065ef0bec7ec8bd3e1d60)
+(B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF, SequenceNumber(2), o#ee32f7158a56efdcfb20ce292f9b6065201f0d9f15dcea67ba3afb572910e3a5)
+
+sui>-$ split-coin --coin-id 1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE --amounts 1000 5000 3000 --gas B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF --gas-budget 1000
+----- Certificate ----
+Signed Authorities : [k#a723959ed6c6d9b4a508fa527c00c215681812b2f0e86c486bbc204ca94f6df9, k#dee2507e5935e836624d66d16817d79426cfbf0a75b39564467463ce619862fa, k#fb942f73e08b2686d0daef41307fd15804bfd953baf497762f36255401d7b2bf]
+Transaction Kind : Call
+Gas Budget : 1000
+Package ID : 0x2
+Module : Coin
+Function : split_vec
+Object Arguments : [(1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, SequenceNumber(2), o#1ce25191bf2832df1bda257044f5764c4ec6144dc6d065ef0bec7ec8bd3e1d60)]
+Pure Arguments : [[3, 232, 3, 0, 0, 0, 0, 0, 0, 136, 19, 0, 0, 0, 0, 0, 0, 184, 11, 0, 0, 0, 0, 0, 0]]
+Type Arguments : [Struct(StructTag { address: 0000000000000000000000000000000000000002, module: Identifier("GAS"), name: Identifier("GAS"), type_params: [] })]
+----- Split Coin Results ----
+Updated Coin : Coin { id: 1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, value: 191000 }
+New Coins : Coin { id: 2311C83B04D0755390C0FA3DA5B0DBF7AA14FADD, value: 3000 },
+ Coin { id: 538D2C507C34BE647A86629CC9509B12FD5330C2, value: 1000 },
+ Coin { id: BFA8BAB64ED8F74BA3731C9220FD7462456BC601, value: 5000 }
+Updated Gas : Coin { id: B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF, value: 99776 }
+
+sui>-$ objects --address 830F66EA8EA867DDCA479535BC12CE2852E571F2
+Showing 5 results.
+(1E1D62BDE28964F6FC0CE3503B5058C4DC04F1DE, SequenceNumber(3), o#300ca9a58cbfdca9e3692378753bf0c15026d21fa8f2e9169f09390a101f1097)
+(2311C83B04D0755390C0FA3DA5B0DBF7AA14FADD, SequenceNumber(1), o#158383eae6edaa37c3679653eb7edd46431a903397a305e15d0c3adadb7957b1)
+(538D2C507C34BE647A86629CC9509B12FD5330C2, SequenceNumber(1), o#d02a23b46168e62525401dbce913105989ebfb9d33045c0e58b8b759b173be29)
+(B7FD91A802DAF5523CAAB69FF4652FAFA6FF4ADF, SequenceNumber(3), o#839e98b33b3de62bc84c36c35b9fd6cdf3383f9d7c4f760c398cbbc7bef8c932)
+(BFA8BAB64ED8F74BA3731C9220FD7462456BC601, SequenceNumber(1), o#6748854128a8b4746fb5bd124eddafc4f9129bae36a8a34af85a8f29b07ee124)
+```
+From the result we can see three new coins were created in the transaction.
## Calling Move code
@@ -398,12 +625,10 @@ command just like we used `0x2` for built-in packages in the
## Customize genesis
The genesis process can be customized by providing a genesis configuration
-file.
-
-TODO: Specify where this file should reside.
+file using the `--config` flag.
```shell
-./sui genesis --config genesis.conf
+./sui genesis --config
```
Example `genesis.conf`:
```json
@@ -435,9 +660,10 @@ Example `genesis.conf`:
```
All attributes in `genesis.conf` are optional, and default values
-will be used if the attributes are not provided. For example, the
+will be used if the attributes are not provided.
+For example, the
config shown below will create a network of four authorities, and
-pre-populate two gas objects for four accounts:
+pre-populate two gas objects for four newly generated accounts:
```json
{
diff --git a/sui/src/wallet.rs b/sui/src/wallet.rs
index c52dc1381f83c..42fed211a4bff 100644
--- a/sui/src/wallet.rs
+++ b/sui/src/wallet.rs
@@ -76,7 +76,7 @@ async fn main() -> Result<(), anyhow::Error> {
println!();
let mut shell = Shell {
- prompt: "sui>-$ ",
+ prompt: "sui>-$ ".bold().green(),
state: context,
handler: ClientCommandHandler,
command: CommandStructure::from_clap(&install_shell_plugins(app)),
diff --git a/sui/src/wallet_commands.rs b/sui/src/wallet_commands.rs
index 3eef9daf5eb60..af5fa2031df2c 100644
--- a/sui/src/wallet_commands.rs
+++ b/sui/src/wallet_commands.rs
@@ -31,6 +31,7 @@ use std::sync::{Arc, RwLock};
use std::time::Instant;
use structopt::clap::AppSettings;
use structopt::StructOpt;
+use sui_core::client::client_responses::{MergeCoinResponse, SplitCoinResponse};
use sui_types::crypto::{Signable, Signature};
use sui_types::object::ObjectRead;
use tracing::info;
@@ -41,7 +42,7 @@ use tracing::info;
pub struct WalletOpts {
#[structopt(subcommand)]
pub command: WalletCommands,
- /// Return command outputs in json format.
+ /// Returns command outputs in JSON format.
#[structopt(long, global = true)]
pub json: bool,
}
@@ -146,6 +147,38 @@ pub enum WalletCommands {
#[structopt(long, parse(try_from_str = decode_bytes_hex))]
address: SuiAddress,
},
+
+ /// Split a coin object into multiple coins.
+ SplitCoin {
+ /// Coin to Split, in 20 bytes Hex string
+ #[structopt(long)]
+ coin_id: ObjectID,
+ /// Amount to split out from the coin
+ #[structopt(long)]
+ amounts: Vec,
+ /// ID of the gas object for gas payment, in 20 bytes Hex string
+ #[structopt(long)]
+ gas: ObjectID,
+ /// Gas budget for this call
+ #[structopt(long)]
+ gas_budget: u64,
+ },
+
+ /// Merge two coin objects into one coin
+ MergeCoin {
+ /// Coin to merge into, in 20 bytes Hex string
+ #[structopt(long)]
+ primary_coin: ObjectID,
+ /// Coin to be merged, in 20 bytes Hex string
+ #[structopt(long)]
+ coin_to_merge: ObjectID,
+ /// ID of the gas object for gas payment, in 20 bytes Hex string
+ #[structopt(long)]
+ gas: ObjectID,
+ /// Gas budget for this call
+ #[structopt(long)]
+ gas_budget: u64,
+ },
}
struct SimpleTransactionSigner {
@@ -171,7 +204,7 @@ impl WalletCommands {
&mut self,
context: &mut WalletContext,
) -> Result {
- let signature_callback = Box::pin(SimpleTransactionSigner {
+ let tx_signer = Box::pin(SimpleTransactionSigner {
keystore: context.keystore.clone(),
});
@@ -202,7 +235,7 @@ impl WalletCommands {
compiled_modules,
gas_obj_ref,
*gas_budget,
- signature_callback,
+ tx_signer,
)
.await?;
@@ -296,7 +329,7 @@ impl WalletCommands {
vec![],
pure_args,
*gas_budget,
- signature_callback,
+ tx_signer,
)
.await?;
if matches!(effects.status, ExecutionStatus::Failure { .. }) {
@@ -315,7 +348,7 @@ impl WalletCommands {
let (cert, effects) = context
.address_manager
- .transfer_coin(*from, *object_id, *gas, *to, signature_callback)
+ .transfer_coin(*from, *object_id, *gas, *to, tx_signer)
.await?;
let time_total = time_start.elapsed().as_micros();
@@ -370,6 +403,54 @@ impl WalletCommands {
}
WalletCommandResult::Gas(coins)
}
+ WalletCommands::SplitCoin {
+ coin_id,
+ amounts,
+ gas,
+ gas_budget,
+ } => {
+ let signer = &context
+ .address_manager
+ .get_object_owner(*gas)
+ .await?
+ .get_single_owner_address()?;
+ let response = context
+ .address_manager
+ .split_coin(
+ *signer,
+ *coin_id,
+ amounts.clone(),
+ *gas,
+ *gas_budget,
+ tx_signer,
+ )
+ .await?;
+ WalletCommandResult::SplitCoin(response)
+ }
+ WalletCommands::MergeCoin {
+ primary_coin,
+ coin_to_merge,
+ gas,
+ gas_budget,
+ } => {
+ let signer = &context
+ .address_manager
+ .get_object_owner(*gas)
+ .await?
+ .get_single_owner_address()?;
+ let response = context
+ .address_manager
+ .merge_coins(
+ *signer,
+ *primary_coin,
+ *coin_to_merge,
+ *gas,
+ *gas_budget,
+ tx_signer,
+ )
+ .await?;
+ WalletCommandResult::MergeCoin(response)
+ }
})
}
}
@@ -460,6 +541,12 @@ impl Display for WalletCommandResult {
)?;
}
}
+ WalletCommandResult::SplitCoin(response) => {
+ write!(writer, "{}", response)?;
+ }
+ WalletCommandResult::MergeCoin(response) => {
+ write!(writer, "{}", response)?;
+ }
}
write!(f, "{}", writer)
}
@@ -525,4 +612,6 @@ pub enum WalletCommandResult {
SyncClientState,
NewAddress(SuiAddress),
Gas(Vec),
+ SplitCoin(SplitCoinResponse),
+ MergeCoin(MergeCoinResponse),
}
diff --git a/sui_core/src/client.rs b/sui_core/src/client.rs
index 18352020dec28..f5d3425ef7454 100644
--- a/sui_core/src/client.rs
+++ b/sui_core/src/client.rs
@@ -216,9 +216,9 @@ pub trait Client {
async fn split_coin(
&mut self,
signer: SuiAddress,
- coin_object_ref: ObjectRef,
+ coin_object_id: ObjectID,
split_amounts: Vec,
- gas_payment: ObjectRef,
+ gas_payment: ObjectID,
gas_budget: u64,
tx_signer: StableSyncTransactionSigner,
) -> Result;
@@ -234,9 +234,9 @@ pub trait Client {
async fn merge_coins(
&mut self,
signer: SuiAddress,
- primary_coin: ObjectRef,
- coin_to_merge: ObjectRef,
- gas_payment: ObjectRef,
+ primary_coin: ObjectID,
+ coin_to_merge: ObjectID,
+ gas_payment: ObjectID,
gas_budget: u64,
tx_signer: StableSyncTransactionSigner,
) -> Result;
@@ -758,12 +758,15 @@ where
async fn split_coin(
&mut self,
signer: SuiAddress,
- coin_object_ref: ObjectRef,
+ coin_object_id: ObjectID,
split_amounts: Vec,
- gas_payment: ObjectRef,
+ gas_payment: ObjectID,
gas_budget: u64,
tx_signer: StableSyncTransactionSigner,
) -> Result {
+ let account = self.get_account(&signer)?;
+ let coin_object_ref = account.latest_object_ref(&coin_object_id)?;
+ let gas_payment = account.latest_object_ref(&gas_payment)?;
let coin_type = self
.get_object_info(coin_object_ref.0)
.await?
@@ -818,12 +821,17 @@ where
async fn merge_coins(
&mut self,
signer: SuiAddress,
- primary_coin: ObjectRef,
- coin_to_merge: ObjectRef,
- gas_payment: ObjectRef,
+ primary_coin: ObjectID,
+ coin_to_merge: ObjectID,
+ gas_payment: ObjectID,
gas_budget: u64,
tx_signer: StableSyncTransactionSigner,
) -> Result {
+ let account = self.get_account(&signer)?;
+ let primary_coin = account.latest_object_ref(&primary_coin)?;
+ let coin_to_merge = account.latest_object_ref(&coin_to_merge)?;
+ let gas_payment = account.latest_object_ref(&gas_payment)?;
+
let coin_type = self
.get_object_info(primary_coin.0)
.await?
diff --git a/sui_core/src/client/client_responses.rs b/sui_core/src/client/client_responses.rs
index 40316a8b16ac5..961283c0a73ef 100644
--- a/sui_core/src/client/client_responses.rs
+++ b/sui_core/src/client/client_responses.rs
@@ -1,9 +1,16 @@
// Copyright (c) 2022, Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
+use serde::ser::Error;
+use serde::Serialize;
+use std::fmt;
+use std::fmt::Write;
+use std::fmt::{Display, Formatter};
+use sui_types::gas_coin::GasCoin;
use sui_types::messages::CertifiedTransaction;
use sui_types::object::Object;
+#[derive(Serialize)]
pub struct SplitCoinResponse {
/// Certificate of the transaction
pub certificate: CertifiedTransaction,
@@ -15,6 +22,32 @@ pub struct SplitCoinResponse {
pub updated_gas: Object,
}
+impl Display for SplitCoinResponse {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut writer = String::new();
+ writeln!(writer, "----- Certificate ----")?;
+ write!(writer, "{}", self.certificate)?;
+ writeln!(writer, "----- Split Coin Results ----")?;
+
+ let coin = GasCoin::try_from(&self.updated_coin).map_err(fmt::Error::custom)?;
+ writeln!(writer, "Updated Coin : {}", coin)?;
+ let mut new_coin_text = Vec::new();
+ for coin in &self.new_coins {
+ let coin = GasCoin::try_from(coin).map_err(fmt::Error::custom)?;
+ new_coin_text.push(format!("{}", coin))
+ }
+ writeln!(
+ writer,
+ "New Coins : {}",
+ new_coin_text.join(",\n ")
+ )?;
+ let gas_coin = GasCoin::try_from(&self.updated_gas).map_err(fmt::Error::custom)?;
+ writeln!(writer, "Updated Gas : {}", gas_coin)?;
+ write!(f, "{}", writer)
+ }
+}
+
+#[derive(Serialize)]
pub struct MergeCoinResponse {
/// Certificate of the transaction
pub certificate: CertifiedTransaction,
@@ -23,3 +56,18 @@ pub struct MergeCoinResponse {
/// The updated gas payment object after deducting payment
pub updated_gas: Object,
}
+
+impl Display for MergeCoinResponse {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ let mut writer = String::new();
+ writeln!(writer, "----- Certificate ----")?;
+ write!(writer, "{}", self.certificate)?;
+ writeln!(writer, "----- Merge Coin Results ----")?;
+
+ let coin = GasCoin::try_from(&self.updated_coin).map_err(fmt::Error::custom)?;
+ writeln!(writer, "Updated Coin : {}", coin)?;
+ let gas_coin = GasCoin::try_from(&self.updated_gas).map_err(fmt::Error::custom)?;
+ writeln!(writer, "Updated Gas : {}", gas_coin)?;
+ write!(f, "{}", writer)
+ }
+}
diff --git a/sui_core/src/unit_tests/client_tests.rs b/sui_core/src/unit_tests/client_tests.rs
index e2df0bcd79e5d..79fe9de3b8e4f 100644
--- a/sui_core/src/unit_tests/client_tests.rs
+++ b/sui_core/src/unit_tests/client_tests.rs
@@ -2516,9 +2516,9 @@ async fn test_coin_split() {
let response = client
.split_coin(
addr1,
- coin_object.to_object_reference(),
+ coin_object.id(),
split_amounts.clone(),
- gas_object.to_object_reference(),
+ gas_object.id(),
GAS_VALUE_FOR_TESTING,
signature_callback(&key1),
)
@@ -2573,9 +2573,9 @@ async fn test_coin_merge() {
let response = client
.merge_coins(
addr1,
- coin_object1.to_object_reference(),
- coin_object2.to_object_reference(),
- gas_object.to_object_reference(),
+ coin_object1.id(),
+ coin_object2.id(),
+ gas_object.id(),
GAS_VALUE_FOR_TESTING,
signature_callback(&key1),
)
diff --git a/sui_types/src/gas_coin.rs b/sui_types/src/gas_coin.rs
index dbf53f4eedea8..b8bbe1acc1205 100644
--- a/sui_types/src/gas_coin.rs
+++ b/sui_types/src/gas_coin.rs
@@ -9,6 +9,7 @@ use move_core_types::{
};
use serde::{Deserialize, Serialize};
use std::convert::{TryFrom, TryInto};
+use std::fmt::{Display, Formatter};
use crate::{
base_types::{ObjectID, SequenceNumber},
@@ -104,3 +105,9 @@ impl TryFrom<&Object> for GasCoin {
}
}
}
+
+impl Display for GasCoin {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "Coin {{ id: {}, value: {} }}", self.id(), self.value())
+ }
+}
diff --git a/sui_types/src/messages.rs b/sui_types/src/messages.rs
index 12f4d4fa2b930..61da72fcde749 100644
--- a/sui_types/src/messages.rs
+++ b/sui_types/src/messages.rs
@@ -729,7 +729,7 @@ impl Display for CertifiedTransaction {
TransactionKind::Call(c) => {
writeln!(writer, "Transaction Kind : Call")?;
writeln!(writer, "Gas Budget : {}", c.gas_budget)?;
- writeln!(writer, "Package ID : {}", c.package.0.to_hex())?;
+ writeln!(writer, "Package ID : {}", c.package.0.to_hex_literal())?;
writeln!(writer, "Module : {}", c.module)?;
writeln!(writer, "Function : {}", c.function)?;
writeln!(writer, "Object Arguments : {:?}", c.object_arguments)?;