Skip to content

Commit

Permalink
pay(all)sui in RPC and CLI (MystenLabs#5385)
Browse files Browse the repository at this point in the history
  • Loading branch information
gegaowp authored Oct 25, 2022
1 parent 6cc1043 commit e1145b2
Show file tree
Hide file tree
Showing 7 changed files with 366 additions and 3 deletions.
3 changes: 3 additions & 0 deletions crates/sui-core/src/gateway_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1629,6 +1629,7 @@ where
Ok(data)
}

// TODO: consolidate this with Pay transactions
async fn split_coin(
&self,
signer: SuiAddress,
Expand Down Expand Up @@ -1660,6 +1661,7 @@ where
Ok(data)
}

// TODO: consolidate this with Pay transactions
async fn split_coin_equal(
&self,
signer: SuiAddress,
Expand Down Expand Up @@ -1691,6 +1693,7 @@ where
Ok(data)
}

// TODO: consolidate this with Pay transactions
async fn merge_coins(
&self,
signer: SuiAddress,
Expand Down
48 changes: 48 additions & 0 deletions crates/sui-json-rpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ pub trait RpcTransactionBuilder {
amount: Option<u64>,
) -> RpcResult<TransactionBytes>;

/// Send Coin<T> to a list of addresses, where `T` can be any coin type, following a list of amounts,
/// The object specified in the `gas` field will be used to pay the gas fee for the transaction.
/// The gas object can not appear in `input_coins`. If the gas object is not specified, the RPC server
/// will auto-select one.
#[method(name = "pay")]
async fn pay(
&self,
Expand All @@ -255,6 +259,50 @@ pub trait RpcTransactionBuilder {
gas_budget: u64,
) -> RpcResult<TransactionBytes>;

/// Send SUI coins to a list of addresses, following a list of amounts.
/// This is for SUI coin only and does not require a separate gas coin object.
/// Specifically, what pay_sui does are:
/// 1. debit each input_coin to create new coin following the order of
/// amounts and assign it to the corresponding recipient.
/// 2. accumulate all residual SUI from input coins left and deposit all SUI to the first
/// input coin, then use the first input coin as the gas coin object.
/// 3. the balance of the first input coin after tx is sum(input_coins) - sum(amounts) - actual_gas_cost
/// 4. all other input coints other than the first one are deleted.
#[method(name = "paySui")]
async fn pay_sui(
&self,
/// the transaction signer's Sui address
signer: SuiAddress,
/// the Sui coins to be used in this transaction, including the coin for gas payment.
input_coins: Vec<ObjectID>,
/// the recipients' addresses, the length of this vector must be the same as amounts.
recipients: Vec<SuiAddress>,
/// the amounts to be transferred to recipients, following the same order
amounts: Vec<u64>,
/// the gas budget, the transaction will fail if the gas cost exceed the budget
gas_budget: u64,
) -> RpcResult<TransactionBytes>;

/// Send all SUI coins to one recipient.
/// This is for SUI coin only and does not require a separate gas coin object.
/// Specifically, what pay_all_sui does are:
/// 1. accumulate all SUI from input coins and deposit all SUI to the first input coin
/// 2. transfer the updated first coin to the recipient and also use this first coin as gas coin object.
/// 3. the balance of the first input coin after tx is sum(input_coins) - actual_gas_cost.
/// 4. all other input coins other than the first are deleted.
#[method(name = "payAllSui")]
async fn pay_all_sui(
&self,
/// the transaction signer's Sui address
signer: SuiAddress,
/// the Sui coins to be used in this transaction, including the coin for gas payment.
input_coins: Vec<ObjectID>,
/// the recipient address,
recipient: SuiAddress,
/// the gas budget, the transaction will fail if the gas cost exceed the budget
gas_budget: u64,
) -> RpcResult<TransactionBytes>;

/// Create an unsigned transaction to execute a Move call on the network, by calling the specified function in the module of a given package.
#[method(name = "moveCall")]
async fn move_call(
Expand Down
29 changes: 29 additions & 0 deletions crates/sui-json-rpc/src/gateway_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,35 @@ impl RpcTransactionBuilderServer for TransactionBuilderImpl {
Ok(TransactionBytes::from_data(data)?)
}

async fn pay_sui(
&self,
signer: SuiAddress,
input_coins: Vec<ObjectID>,
recipients: Vec<SuiAddress>,
amounts: Vec<u64>,
gas_budget: u64,
) -> RpcResult<TransactionBytes> {
let data = self
.client
.pay_sui(signer, input_coins, recipients, amounts, gas_budget)
.await?;
Ok(TransactionBytes::from_data(data)?)
}

async fn pay_all_sui(
&self,
signer: SuiAddress,
input_coins: Vec<ObjectID>,
recipient: SuiAddress,
gas_budget: u64,
) -> RpcResult<TransactionBytes> {
let data = self
.client
.pay_all_sui(signer, input_coins, recipient, gas_budget)
.await?;
Ok(TransactionBytes::from_data(data)?)
}

async fn publish(
&self,
sender: SuiAddress,
Expand Down
29 changes: 29 additions & 0 deletions crates/sui-json-rpc/src/transaction_builder_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,35 @@ impl RpcTransactionBuilderServer for FullNodeTransactionBuilderApi {
Ok(TransactionBytes::from_data(data)?)
}

async fn pay_sui(
&self,
signer: SuiAddress,
input_coins: Vec<ObjectID>,
recipients: Vec<SuiAddress>,
amounts: Vec<u64>,
gas_budget: u64,
) -> RpcResult<TransactionBytes> {
let data = self
.builder
.pay_sui(signer, input_coins, recipients, amounts, gas_budget)
.await?;
Ok(TransactionBytes::from_data(data)?)
}

async fn pay_all_sui(
&self,
signer: SuiAddress,
input_coins: Vec<ObjectID>,
recipient: SuiAddress,
gas_budget: u64,
) -> RpcResult<TransactionBytes> {
let data = self
.builder
.pay_all_sui(signer, input_coins, recipient, gas_budget)
.await?;
Ok(TransactionBytes::from_data(data)?)
}

async fn publish(
&self,
sender: SuiAddress,
Expand Down
127 changes: 127 additions & 0 deletions crates/sui-open-rpc/spec/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,7 @@
"name": "Transaction Builder API"
}
],
"description": "Send Coin<T> to a list of addresses, where `T` can be any coin type, following a list of amounts, The object specified in the `gas` field will be used to pay the gas fee for the transaction. The gas object can not appear in `input_coins`. If the gas object is not specified, the RPC server will auto-select one.",
"params": [
{
"name": "signer",
Expand Down Expand Up @@ -2109,6 +2110,132 @@
}
}
},
{
"name": "sui_payAllSui",
"tags": [
{
"name": "Transaction Builder API"
}
],
"description": "Send all SUI coins to one recipient. This is for SUI coin only and does not require a separate gas coin object. Specifically, what pay_all_sui does are: 1. accumulate all SUI from input coins and deposit all SUI to the first input coin 2. transfer the updated first coin to the recipient and also use this first coin as gas coin object. 3. the balance of the first input coin after tx is sum(input_coins) - actual_gas_cost. 4. all other input coins other than the first are deleted.",
"params": [
{
"name": "signer",
"description": "the transaction signer's Sui address",
"required": true,
"schema": {
"$ref": "#/components/schemas/SuiAddress"
}
},
{
"name": "input_coins",
"description": "the Sui coins to be used in this transaction, including the coin for gas payment.",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ObjectID"
}
}
},
{
"name": "recipient",
"description": "the recipient address,",
"required": true,
"schema": {
"$ref": "#/components/schemas/SuiAddress"
}
},
{
"name": "gas_budget",
"description": "the gas budget, the transaction will fail if the gas cost exceed the budget",
"required": true,
"schema": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
],
"result": {
"name": "TransactionBytes",
"required": true,
"schema": {
"$ref": "#/components/schemas/TransactionBytes"
}
}
},
{
"name": "sui_paySui",
"tags": [
{
"name": "Transaction Builder API"
}
],
"description": "Send SUI coins to a list of addresses, following a list of amounts. This is for SUI coin only and does not require a separate gas coin object. Specifically, what pay_sui does are: 1. debit each input_coin to create new coin following the order of amounts and assign it to the corresponding recipient. 2. accumulate all residual SUI from input coins left and deposit all SUI to the first input coin, then use the first input coin as the gas coin object. 3. the balance of the first input coin after tx is sum(input_coins) - sum(amounts) - actual_gas_cost 4. all other input coints other than the first one are deleted.",
"params": [
{
"name": "signer",
"description": "the transaction signer's Sui address",
"required": true,
"schema": {
"$ref": "#/components/schemas/SuiAddress"
}
},
{
"name": "input_coins",
"description": "the Sui coins to be used in this transaction, including the coin for gas payment.",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ObjectID"
}
}
},
{
"name": "recipients",
"description": "the recipients' addresses, the length of this vector must be the same as amounts.",
"required": true,
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SuiAddress"
}
}
},
{
"name": "amounts",
"description": "the amounts to be transferred to recipients, following the same order",
"required": true,
"schema": {
"type": "array",
"items": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
},
{
"name": "gas_budget",
"description": "the gas budget, the transaction will fail if the gas cost exceed the budget",
"required": true,
"schema": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
],
"result": {
"name": "TransactionBytes",
"required": true,
"schema": {
"$ref": "#/components/schemas/TransactionBytes"
}
}
},
{
"name": "sui_publish",
"tags": [
Expand Down
3 changes: 3 additions & 0 deletions crates/sui-transaction-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ impl TransactionBuilder {
))
}

// TODO: consolidate this with Pay transactions
pub async fn split_coin(
&self,
signer: SuiAddress,
Expand Down Expand Up @@ -395,6 +396,7 @@ impl TransactionBuilder {
))
}

// TODO: consolidate this with Pay transactions
pub async fn split_coin_equal(
&self,
signer: SuiAddress,
Expand Down Expand Up @@ -426,6 +428,7 @@ impl TransactionBuilder {
))
}

// TODO: consolidate this with Pay transactions
pub async fn merge_coins(
&self,
signer: SuiAddress,
Expand Down
Loading

0 comments on commit e1145b2

Please sign in to comment.