0.45.0 • Published 8 days ago

@scallop-io/sui-kit v0.45.0

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
8 days ago

Tookit for interacting with SUI network

Features

  • Transfer SUI, Custom Coin and objects.
  • Move call
  • Programmable transaction
  • Query on-chain data
  • HD wallet multi-accounts

Pre-requisites

npm install @scallop-io/sui-kit

How to use

Init SuiKit

import { SuiKit } from '@scallop-io/sui-kit';

// The following types of secret key are supported:
// 1. base64 key from SUI cli keystore file
// 2. 32 bytes hex key
// 3. 64 bytes legacy hex key
const secretKey = '<Secret key>';
const suiKit1 = new SuiKit({ secretKey });

// 12 or 24 words mnemonics
const mnemonics = '<Mnemonics>';
const suiKit2 = new SuiKit({ mnemonics });

// It will create a HD wallet with a random mnemonics
const suiKit3 = new SuiKit();

// Override options
const suiKit = new SuiKit({
  mnemonics: '<Mnemonics>',
  // 'testnet' | 'mainnet' | 'devnet', default is 'devnet'
  networkType: 'testnet',
  // the fullnode url, default is the preconfig fullnode url for the given network type
  // It will rotate the fullnode when the current fullnode is not available
  fullnodeUrls: '[<SUI fullnode1>, <SUI fullnode2>]',
  // the faucet url, default is the preconfig faucet url for the given network type
  faucetUrl: '<SUI faucet url>',
});

Transfer

You can use SuiKit to transfer SUI, custom coins, and any objects.

const recipient1 = '0x123'; // repace with real address
const recipient2 = '0x456'; // repace with real address

// transfer SUI to single recipient
await suiKit.transferSui(recipient1, 1000);
// transfer SUI to multiple recipients
await suiKit.transferSuiToMany([recipient1, recipient2], [1000, 2000]);

const coinType = '<pkgId>::custom_coin::CUSTOM_COIN';
// Transfer custom coin to single recipient
await suiKit.transferCoin(recipient1, 1000, coinType);
// Transfer custom coin to multiple recipients
await suiKit.transferCoinToMany(
  [recipient1, recipient2],
  [1000, 2000],
  coinType
);

// Transfer objects
const objectIds = ['<objId1>', '<objId2>'];
await suiKit.transferObjects(objectIds, recipient1);

Stake SUI

You can use SuiKit to stake SUI.

/**
 * This is an example of using SuiKit to stake SUI
 */
const stakeAmount = 1000;
const validatorAddress = '0x123'; // replace with real address
suiKit.stakeSui(stakeAmount, validatorAddress).then(() => {
  console.log('Stake SUI success');
});

Move call

You can use SuiKit to call move functions.

const res = await suiKit.moveCall({
  target: '0x2::coin::join',
  arguments: [coin0, coin1],
  typeArguments: [coinType],
});
console.log(res);

How to pass arguments? Suppose you have a move function like this:

public entry fun test_args(
  addrs: vector<address>,
  name: vector<u8>,
  numbers: vector<u64>,
  bools: vector<bool>,
  coins: vector<Coin<SUI>>,
  ctx: &mut TxContext,
) {
  // ...
}

You can pass the arguments like this:

const addr1 =
  '0x656b875c9c072a465048fc10643470a39ba331727719df46c004973fcfb53c95';
const addr2 =
  '0x10651e50cdbb4944a8fd77665d5af27f8abde6eb76a12b97444809ae4ddb1aad';
const coin1 =
  '0xd4a01b597b87986b04b65e04049499b445c0ee901fe8ba310b1cf29feaa86876';
const coin2 =
  '0x4d4a01b597b87986b04b65e04049499b445c0ee901fe8ba310b1cf29feaa8687';
suiKit.moveCall({
  target: `${pkgId}::module::test_args`,
  arguments: [
    // pass vector<address>, need to specify the vecType as 'address'
    { value: [addr1, addr2], vecType: 'address' },
    // pass vector<u8>, need to specify the vecType as 'u8'
    { value: [10, 20], vecType: 'u8' },
    // pass vector<u64>, default vecType for number array is 'u64', so no need to specify
    [34324, 234234],
    // pass vector<bool>, default vecType for boolean array is 'bool', so no need to specify
    [true, false],
    // pass vector<Coin<SUI>>, no need to specify the vecType for object array
    [coin1, coin2],
  ],
});

All the supported types are:

  • address
  • u8
  • u16
  • u32
  • u64
  • u128
  • u256
  • bool
  • object

Programmable transaction

With programmable transaction, you can send a transaction with multiple actions. The following is an example using flashloan to make arbitrage. (check here for the corresponding Move contract code)

import { SuiKit, SuiTxBlock } from '@scallop-io/sui-kit';
import * as process from 'process';
import * as dotenv from 'dotenv';
dotenv.config();

const treasuryA =
  '0xe5042357d2c2bb928f37e4d12eac594e6d02327d565e801eaf9aca4c7340c28c';
const treasuryB =
  '0xdd2f53171b8c886fad20e0bfecf1d4eede9d6c75762f169a9f3c3022e5ce7293';
const dexPool =
  '0x8a13859a8d930f3238ddd31180a5f0914e5b8dbaa31e18387066b61a563fedf9';

const pkgId =
  '0x3c316b6af0586343ce8e6b4be890305a1f83b7e196366f6435b22b6e3fc8e3d9';

(async () => {
  const mnemonics = process.env.MNEMONICS;
  const suiKit = new SuiKit({ mnemonics });
  const sender = suiKit.currentAddress();

  const tx = new SuiTxBlock();
  // 1. Make a flash loan for coinB
  const [coinB, loan] = tx.moveCall(`${pkgId}::custom_coin_b::flash_loan`, [
    treasuryB,
    10 ** 9,
  ]);
  // 2. Swap from coinB to coinA, ratio is 1:1
  const coinA = tx.moveCall(`${pkgId}::dex::swap_a`, [dexPool, coinB]);
  // 3. Swap from coinA back to coinB, ratio is 1:2
  const coinB2 = tx.moveCall(`${pkgId}::dex::swap_b`, [dexPool, coinA]);
  // 4. Repay flash loan
  const [paybackCoinB] = tx.splitCoins(coinB2, [10 ** 9]);
  tx.moveCall(`${pkgId}::custom_coin_b::payback_loan`, [
    treasuryB,
    paybackCoinB,
    loan,
  ]);
  // 4. Transfer profits to sender
  tx.transferObjects([coinB2], sender);

  // 5. Execute transaction
  const res = await suiKit.signAndSendTxn(tx);
  console.log(res);
})();

Multi-accounts

SuiKit follows bip32 & bip39 standard, so you can use it to manage multiple accounts. When init SuiKit, you can pass in your mnemonics to create a wallet with multiple accounts.

/**
 * This is an example of using SuiKit to manage multiple accounts.
 */
import { SuiKit } from '@scallop-io/sui-kit';

async function checkAccounts(suiKit: SuiKit) {
  const displayAccounts = async (suiKit: SuiKit, accountIndex: number) => {
    const coinType = '0x2::sui::SUI';
    const addr = suiKit.getAddress({ accountIndex });
    const balance = (await suiKit.getBalance(coinType, { accountIndex }))
      .totalBalance;
    console.log(`Account ${accountIndex}: ${addr} has ${balance} SUI`);
  };
  // log the first 10 accounts
  const numAccounts = 10;
  for (let i = 0; i < numAccounts; i++) {
    await displayAccounts(suiKit, i);
  }
}

async function internalTransferSui(
  suiKit: SuiKit,
  fromAccountIndex: number,
  toAccountIndex: number,
  amount: number
) {
  const toAddr = suiKit.getAddress({ accountIndex: toAccountIndex });
  console.log(
    `Transfer ${amount} SUI from account ${fromAccountIndex} to account ${toAccountIndex}`
  );
  return await suiKit.transferSui(toAddr, amount, {
    accountIndex: fromAccountIndex,
  });
}

const mnemonics = process.env.MNEMONICS;
const suiKit = new SuiKit({ mnemonics });
checkAccounts(suiKit).then(() => {});
// transfer 1000 SUI from account 0 to account 1
internalTransferSui(suiKit, 0, 1, 1000).then(() => {});

Publish & upgrade Move package

We have a standalone npm package to help you publish and upgrade Move package based on sui-kit.

Please refer to the repository: sui-package-kit

0.45.0

8 days ago

0.44.2

4 months ago

0.44.1

5 months ago

0.42.0

8 months ago

0.42.1

7 months ago

0.41.0

9 months ago

0.38.2

10 months ago

0.38.1

10 months ago

0.38.0

10 months ago

0.37.1

11 months ago

0.37.0

11 months ago

0.44.0

7 months ago

0.42.2

7 months ago

0.36.1

11 months ago

0.36.0

11 months ago

0.35.3

11 months ago

0.35.2

11 months ago

0.35.1

11 months ago

0.34.1

12 months ago

0.34.0

12 months ago

0.33.1

1 year ago

0.33.0

1 year ago

0.32.12

1 year ago