Skip to content

Commit

Permalink
Create prog-trans-ts-sdk.md (MystenLabs#9609)
Browse files Browse the repository at this point in the history
## Description 

Describe the changes or additions included in this PR.

## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

---------

Co-authored-by: ronny-mysten <[email protected]>
  • Loading branch information
randall-Mysten and ronny-mysten authored Mar 21, 2023
1 parent c069aa0 commit 4082fab
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 26 deletions.
234 changes: 234 additions & 0 deletions doc/src/build/prog-trans-ts-sdk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
---
title: Sui Programmable Transaction with the TS SDK
---

In Sui, all user-initiated transactions are called Programmable Transactions.

## Get Started

First, make sure that you have the latest TypeScript SDK installed.

We’ll start by constructing a transaction to send Sui. If you are familiar with the legacy transaction types, this is similar to a `paySui` transaction. You can start constructing transactions by importing the `Transaction` class, and constructing it:

```tsx
import { Transaction } from '@mysten/sui.js';
const tx = new Transaction();
```

Using this, you can then add commands to this transaction.

```tsx
// Create a new coin with balance 100, based on the coins used as gas payment.
// You can define any balance here.
const coin = tx.splitCoin(tx.gas, tx.pure(100));

// Transfer the split coin to a specific address.
tx.transferObjects([coin], tx.pure('0xSomeSuiAddress'));
```

Note that you can attach multiple of the same command type to a transaction as well. For example, we can get a list of transfers, and iterate over them to transfer coins to each of them:

```tsx
interface Transfer {
to: string;
amount: number;
}

// Procure a list of some Sui transfers we need to make:
const transfers: Transfer[] = getTransfers();

const tx = new Transaction();

// Create commands for each transfer
transfers.forEach((transfer) => {
const coin = tx.splitCoin(tx.gas, tx.pure(transfer.amount));
tx.transferObjects([coin], tx.pure(transfer.to));
});
```

After you have the transaction defined, you can directly execute it with a signer using `signAndExecuteTransaction`.

```tsx
signer.signAndExecuteTransaction({ transaction: tx });
```

## Inputs and commands

Programmable Transactions have two key concepts: inputs and commands.

Inputs are values that are used as arguments to the commands in the transaction. Inputs can either be an object reference (either to an owned object, or a shared object), or a pure BCS value (for example, an encoded string used as an argument to a move call).

Commands are steps of execution in the transaction. You can also use the result of previous commands as arguments to a future command. By combining multiple commands together, programmable transactions provide a flexible way to create complex transactions.

## Constructing inputs

Inputs are how you provide external values to transactions. For example, defining an amount of Sui to transfer, or which object to pass into a move call, or a shared object. There are currently two ways to define inputs:

- **For objects:** the `tx.object(objectId)` function is used to construct an input that contains an object reference.
- **For pure values:** the `tx.pure(rawValue)` function is used, and returns an input reference that you use in commands.

## Available commands

The following commands are available:

- `tx.splitCoin(coin, amount)` - Creates a new coin with the defined amount, split from the provided coin. Returns the coin so that it can be used in subsequent commands.
- Example: `tx.splitCoin(tx.gas, tx.pure(100))`
- `tx.mergeCoins(destinationCoin, sourceCoins)` - Merges the sourceCoins into the destinationCoin.
- Example: `tx.mergeCoins(tx.object(coin1), [tx.object(coin2), tx.object(coin3)])`
- `tx.transferObjects(objects, address)` - Transfers a list of objects to the specified address.
- Example: `tx.transferObjects([tx.object(thing1), tx.object(thing2)], tx.pure(myAddress))`
- `tx.moveCall({ target, arguments, typeArguments })` - Executes a move call. Returns whatever the move call returns.
- Example: `tx.moveCall({ target: '0x2::devnet_nft::mint', arguments: [tx.pure(name), tx.pure(description), tx.pure(image)] })`
- `tx.makeMoveVec({ type, objects })` - Constructs a vector of objects that can be passed into a `moveCall`. This is required as there’s no way to define a vector as an input.
- Example: `tx.makeMoveVec({ objects: [tx.object(id1), tx.object(id2)] })`
- `tx.publish(modules, dependencies)` - Publishes a Move package. Returns the upgrade capability object.

## Passing command results as arguments

You can use the result of a command as an argument in a subsequent command. Each command method on the transaction builder returns a reference to the command result.

```tsx
// Split a coin object off of the gas object:
const coin = tx.splitCoin(tx.gas, tx.pure(100);
// Transfer the resulting coin object:
tx.transferObjects([coin], tx.pure(address));
```
When a command returns multiple results, you can access the result at a specific index either using destructuring, or array indexes.
```tsx
// Destructuring (preferred, as it gives you logical local names):
const [nft1, nft2] = tx.moveCall({ target: '0x2::nft::mint_many' });
tx.transferObjects([nft1, nft2], tx.pure(address));

// Array indexes:
const mintMany = tx.moveCall({ target: '0x2::nft::mint_many' });
tx.transferObjects([mintMany[0], mintMany[1]], tx.pure(address));
```
## Use the gas coin
With Programmable Transactions, you’re able to use the gas payment coin to construct coins with a set balance using `splitCoin`. This is useful for Sui payments, and avoids the need for up-front coin selection. You can use `tx.gas` to access the gas coin in a transaction, and is valid as input for any arguments.
You can also transfer the gas coin using `transferObjects`, in the event that you want to transfer all of your coin balance to another address.
## Get Transaction Bytes
If you need the transaction bytes, instead of signing or executing the transaction, you can use the `build` method on the transaction builder itself.
**Important:** You might need to explicitly call `setSender()` on the transaction to ensure that the `sender` field has been populated. This is normally done by the signer before signing the transaction, but will not be done automatically if you’re building the transaction bytes yourself.
```tsx
const tx = new Transaction();

// ... add some commands...

await tx.build({ provider });
```
In most cases, building requires your JSON RPC Provider to fully resolve input values.
If you have transaction bytes, you can also convert them back into a `Transaction` class:
```tsx
const bytes = getTransactionBytesFromSomewhere();
const tx = Transaction.from(bytes);
```
## Building Offline
In the event that you want to build a transaction offline (i.e. with no `provider` required), you need to fully define all of your input values, and gas configuration (see the following example). For pure values, you can provide a `Uint8Array` which will be used directly in the transaction. For objects, you can use the `Inputs` helper to construct an object reference.
```tsx
import { Inputs } from '@mysten/sui.js';

// For pure values:
tx.pure(pureValueAsBytes);

// For owned or immutable objects:
tx.object(Inputs.ObjectRef({ digest, objectId, version }));

// For shared objects:
tx.object(Inputs.SharedObjectRef({ objectId, initialSharedVersion, mutable }));
```
You can then omit the `provider` object when calling `build` on the transaction. If there is any required data that is missing, this will throw an error.
## Gas Configuration
The new transaction builder comes with default behavior for all gas logic, including automatically setting the gas price, budget, and selecting coins to be used as gas. This behavior can be customized.
### Gas Price
By default, the gas price is set to the reference gas price of the network. You can also explicitly set the gas price of the transaction by calling `setGasPrice` on the transaction builder.
```tsx
tx.setGasPrice(gasPrice);
```
### Budget
By default, the gas budget is automatically derived by executing a dry-run of the transaction beforehand. The dry run gas consumption is then used to determine a balance for the transaction. You can override this behavior by explicitly setting a gas budget for the transaction, by calling `setGasBudget` on the transaction builder.
**Note:** The gas budget is represented in Sui, and should take the gas price of the transaction into account.
```tsx
tx.setGasBudget(gasBudgetAmount);
```
### Gas Payment
By default, the gas payment is automatically determined by the SDK. The SDK will select all of the users coins that are not used as inputs in the transaction.
The list of coins used as gas payment will be merged down into a single gas coin before executing the transaction, and all but one of the gas objects will be deleted. The gas coin at the 0-index will be the coin that all others are merged into.
```tsx
// NOTE: You need to ensure that the coins do not overlap with any
// of the input objects for the transaction.
tx.setGasPayment([coin1, coin2]);
```
### Dapp / Wallet Integration
The Wallet Standard interface has been updated to support the `Transaction` kind directly. All `signTransaction` and `signAndExecuteTransaction` calls from dapps into wallets will be expected to provide a `Transaction` class. This transaction class can then be serialized and sent to your wallet for execution.
To serialize a transaction for sending to a wallet, we recommend using the `tx.serialize()` function, which returns an opaque string representation of the transaction that can be passed from the wallet standard dapp context to your wallet. This can then be converted back into a `Transaction` using `Transaction.from()`.
**Important:** The transaction should not be built from bytes in the dApp code. Using `serialize` instead of `build` allows you to build the transaction bytes within the wallet itself. This allows the wallet to perform gas logic and coin selection as needed.
```tsx
// Within a dApp
const tx = new Transaction();
wallet.signTransaction({ transaction: tx });

// Your wallet standard code:
function handleSignTransaction(input) {
sendToWalletContext({ transaction: input.transaction.serialize() });
}

// Within your wallet context:
function handleSignRequest(input) {
const userTx = Transaction.from(input.transaction);
}
```
## Sponsored Transactions
The transaction builder can support sponsored transaction by using the `onlyTransactionKind` flag when building the transaction.
```tsx
const tx = new Transaction();

// ... add some commands...

const kindBytes = await tx.build({ provider, onlyTransactionKind: true });

// Construct a sponsored transaction from the kind bytes:
const sponsoredTx = Transaction.fromKind(kindBytes);

// You can now set the sponsored transaction data that is required:
sponsoredTx.setSender(sender);
sponsoredTx.setGasOwner(sponsor);
sponsoredTx.setGasPayment(sponsorCoins);
```
28 changes: 6 additions & 22 deletions doc/src/doc-updates/sui-breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,16 @@ The next release of Sui, release 0.28, includes the breaking changes described i

To learn how to update your project to work with the changes introduced in release .28, see the [Sui Migration Guide](sui-migration-guide.md).

New entries added 03/14/23.

Added 03/14/23
New entries added 03/20/23.

**[Major breaking change]** - Sui now calculates `SuiAddress` using the first 32 bytes of the Blake2b hash of `flag || pubkey` instead of the SHA3_256 hash. See [PR 9262](https://github.com/MystenLabs/sui/pull/9262) for more information.

---

Added 03/13/23

**[Major breaking change]** - This release replaces the `sui_getValidators` and `sui_getSuiSystemState` functions with a new `sui_getLatestSuiSystemState` function. The new function returns a flattened type that contains all information from the latest `SuiSystemState` object on-chain with type `SuiSystemStateSummary`. It also contains a vector of type `SuiValidatorSummary` that summarizes information from each validator, including: metadata, staking pool, and other data. The release also adds a `p2p_address` to each validator’s metadata. The value for the field is the address the validator used for p2p activities, such as state sync.

---

Added 03/13/23

**[Major breaking change]** - This release changes the serialization format of Sui object types. Sui now uses a more compact serialization format for common types such as `Coin<SUI>`, `Coin<T>`, and `StakedSui`, reducing object size by up to 40%. This lowers storage gas costs for objects of these types. This doesn’t effect clients using JSON-RPC API read functions, but clients that read raw Sui objects directly need to understand the new type encoding. Note that the encoding of Sui Move structs remains unchanged. See [PR 9055](https://github.com/MystenLabs/sui/pull/9055) for more details.

---
Expand All @@ -42,8 +36,6 @@ Added 03/13/23

---

Added 03/14/23

**[Breaking change]** - This release introduces several limits on transactions and transaction executions. Many of these limits are subject to change prior to Sui Mainnet. To view a list of limits in release .28, see the [source code](https://github.com/MystenLabs/sui/blob/main/crates/sui-protocol-config/src/lib.rs#L716).

---
Expand Down Expand Up @@ -76,20 +68,14 @@ Added 03/14/23

---

Added 03/13/23

**[Minor breaking change]** - Removes `Randomness` from the Sui Framework and the `sui_tblsSignRandomnessObject` JSON RPC. See [PR 8977](https://github.com/MystenLabs/sui/pull/8977) for more information.

---

Added 03/13/23

**[Minor breaking change]** - This changes the genesis snapshot since the generation for a PoP changed. It also removes Sui Move APIs `bls12381::bls12381_min_sig_verify_with_domain`, and `validator::verify_proof_of_possession` because now all validate PoP is now done in `validator::validate_metadata`.

---

Added 3/9/23

**[Major API breaking changes]** - `GetTransaction` API refactoring

* [RPC] `sui_getTransaction` and `sui_multiGetTransaction` now take in an additional optional parameter called `options` that specifies which fields to retrieve (such as `transaction`, `effects`, `events`, etc). By default, these operations return only the transaction digest.
Expand All @@ -99,8 +85,6 @@ For more information, see [PR 8888](https://github.com/MystenLabs/sui/pull/8888)

---

Added 3/9/23

**[Major API breaking changes] sui_executeTransaction refactoring**
* Removed `sui_executeTransactionSerializedSig` and `sui_submitTransaction` operations.
* The `sui_executeTransaction` operation now takes a vector of signatures instead of a single signature to support Sponsored Transactions.
Expand All @@ -109,8 +93,6 @@ To learn more, see [PR 9068](https://github.com/MystenLabs/sui/pull/9068).

---

Added 03/13/23

**[RPC API breaking change]** - Various changes in JSON-RPC governance API:
* updated `sui_getDelegatedStakes` to the new staking flow
* grouped all `StakedSui` by staking pool to reduce duplicate validator info in the response
Expand All @@ -122,13 +104,15 @@ For more information, see [PR 8848](https://github.com/MystenLabs/sui/pull/8848)

---

Added 03/13/23
Added 03/20/23

**[API breaking change]** - This release removes locked coin staking functionality, and changes the layout of the StakedSui object to remove the locking period field. For more information, see [PR 9046](https://github.com/MystenLabs/sui/pull/9046).
**[API breaking change]** - A valid signature must be committed to the Blake2b hash of the message before passing to any signing APIs. If a signature is created elsewhere, please ensure the transaction data is hashed first. For more information, see [PR 9561](https://github.com/MystenLabs/sui/pull/9561).

---

Added 03/13/23
**[API breaking change]** - This release removes locked coin staking functionality, and changes the layout of the StakedSui object to remove the locking period field. For more information, see [PR 9046](https://github.com/MystenLabs/sui/pull/9046).

---

**[API breaking change]** - All functions that include *delegation* in their name are renamed to use *stake* instead. For example, `request_add_delegation` is now `request_add_stake`. See [PR 9059](https://github.com/MystenLabs/sui/pull/9059) for details.

Expand Down
3 changes: 1 addition & 2 deletions doc/src/learn/sponsored-transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ pub struct GasLessTransactionData {
## Create a sponsor-initiated sponsored transaction

A sponsor-initiated sponsored transaction involves the following steps:
1. A sponsor constructs a `TransactionData` object that contains the transaction details and associated gas fee data. The sponsor signs it to generate a `Signature` before sending it to a user.
You can send the unsigned `TransactionData` via email, SMS, or an application interface.
1. A sponsor constructs a `TransactionData` object that contains the transaction details and associated gas fee data. The sponsor signs it to generate a `Signature` before sending it to a user. You can send the unsigned `TransactionData` via email, SMS, or an application interface.
1. The user checks the transaction and signs it to generate the second `Signature` for the transaction.
1. The user submits the dual-signed transaction to a Sui Full node or sponsor to execute it.

Expand Down
9 changes: 7 additions & 2 deletions doc/src/navconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"link": "doc-updates/sui-migration-guide"
},
{
"label": "Sui Upcoming Breaking Changes",
"label": "Sui Breaking Changes",
"link": "doc-updates/sui-breaking-changes"
},
{
Expand Down Expand Up @@ -198,7 +198,12 @@
"label": "Connect to Sui",
"fileName": "build/comms",
"title": "Connect to Sui",
"items": [{
"items": [
{
"label": "Programmable Transactions with TypeScript SDK",
"fileName": "build/prog-trans-ts-sdk"
},
{
"label": "JSON-RPC API",
"fileName": "build/json-rpc"
},
Expand Down

0 comments on commit 4082fab

Please sign in to comment.