@scallop-io/sui-kit 1.4.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +32 -0
  3. package/dist/index.d.cts +747 -0
  4. package/dist/index.d.ts +745 -6
  5. package/dist/index.js +13 -29
  6. package/package.json +14 -13
  7. package/src/index.ts +10 -6
  8. package/src/libs/multiSig/client.ts +1 -1
  9. package/src/libs/multiSig/index.ts +1 -1
  10. package/src/libs/suiAccountManager/index.ts +7 -4
  11. package/src/libs/suiAccountManager/keypair.ts +1 -1
  12. package/src/libs/suiInteractor/index.ts +7 -1
  13. package/src/libs/suiInteractor/suiInteractor.ts +150 -71
  14. package/src/libs/suiModel/index.ts +2 -2
  15. package/src/libs/suiModel/suiOwnedObject.ts +17 -8
  16. package/src/libs/suiTxBuilder/index.ts +24 -13
  17. package/src/libs/suiTxBuilder/util.ts +40 -5
  18. package/src/suiKit.ts +62 -32
  19. package/src/types/index.ts +17 -3
  20. package/dist/index.mjs +0 -15
  21. package/dist/libs/multiSig/client.d.ts +0 -15
  22. package/dist/libs/multiSig/index.d.ts +0 -1
  23. package/dist/libs/multiSig/publickey.d.ts +0 -2
  24. package/dist/libs/suiAccountManager/crypto.d.ts +0 -1
  25. package/dist/libs/suiAccountManager/index.d.ts +0 -39
  26. package/dist/libs/suiAccountManager/keypair.d.ts +0 -21
  27. package/dist/libs/suiAccountManager/util.d.ts +0 -29
  28. package/dist/libs/suiInteractor/index.d.ts +0 -1
  29. package/dist/libs/suiInteractor/suiInteractor.d.ts +0 -39
  30. package/dist/libs/suiInteractor/util.d.ts +0 -2
  31. package/dist/libs/suiModel/index.d.ts +0 -2
  32. package/dist/libs/suiModel/suiOwnedObject.d.ts +0 -24
  33. package/dist/libs/suiModel/suiSharedObject.d.ts +0 -11
  34. package/dist/libs/suiTxBuilder/index.d.ts +0 -637
  35. package/dist/libs/suiTxBuilder/util.d.ts +0 -43
  36. package/dist/suiKit.d.ts +0 -128
  37. package/dist/types/index.d.ts +0 -76
package/dist/index.js CHANGED
@@ -1,31 +1,15 @@
1
- 'use strict';
1
+ import { SUI_SYSTEM_STATE_OBJECT_ID, normalizeStructTag, SUI_TYPE_ARG, isValidSuiAddress, normalizeSuiAddress, isValidSuiObjectId, normalizeSuiObjectId } from '@mysten/sui/utils';
2
+ export * from '@mysten/sui/utils';
3
+ import { Transaction, Inputs, getPureBcsSchema } from '@mysten/sui/transactions';
4
+ export * from '@mysten/sui/transactions';
5
+ import { Ed25519Keypair, Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519';
6
+ import { fromHex, fromBase64, SerializedBcs, isSerializedBcs, bcs } from '@mysten/bcs';
7
+ import { generateMnemonic } from '@scure/bip39';
8
+ import { wordlist } from '@scure/bip39/wordlists/english';
9
+ import { SUI_PRIVATE_KEY_PREFIX, decodeSuiPrivateKey } from '@mysten/sui/cryptography';
10
+ import { SuiGrpcClient } from '@mysten/sui/grpc';
11
+ import { MultiSigPublicKey } from '@mysten/sui/multisig';
2
12
 
3
- var utils = require('@mysten/sui/utils');
4
- var transactions = require('@mysten/sui/transactions');
5
- var client = require('@mysten/sui/client');
6
- var ed25519 = require('@mysten/sui/keypairs/ed25519');
7
- var bcs = require('@mysten/bcs');
8
- var bip39 = require('@scure/bip39');
9
- var english = require('@scure/bip39/wordlists/english');
10
- var cryptography = require('@mysten/sui/cryptography');
11
- var multisig = require('@mysten/sui/multisig');
13
+ var Y=(r={})=>{let{accountIndex:t=0,isExternal:e=!1,addressIndex:i=0}=r;return `m/44'/784'/${t}'/${e?1:0}'/${i}'`},b=(r,t={})=>{let e=Y(t);return Ed25519Keypair.deriveKeypair(r,e)};var X=r=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(r),H=r=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(r),B=r=>{if(X(r))return fromHex(r);if(H(r))return fromBase64(r);throw new Error("The string is not a valid hex or base64 string.")},O=32,L=64,w=r=>{if(r.length===L)return r.slice(0,O);if(r.length===O+1&&r[0]===0)return r.slice(1);if(r.length===O)return r;throw new Error("invalid secret key")};var I=(r=24)=>generateMnemonic(wordlist,r===12?128:256);var S=class{mnemonics;secretKey;currentKeyPair;currentAddress;constructor({mnemonics:t,secretKey:e}={}){this.mnemonics=t||"",this.secretKey=e||"",!this.mnemonics&&!this.secretKey&&(this.mnemonics=I(24)),this.currentKeyPair=this.secretKey?this.parseSecretKey(this.secretKey):b(this.mnemonics),this.currentAddress=this.currentKeyPair.getPublicKey().toSuiAddress();}parseSecretKey(t){if(t.startsWith(SUI_PRIVATE_KEY_PREFIX)){let{secretKey:e}=decodeSuiPrivateKey(t);return Ed25519Keypair.fromSecretKey(w(e))}return Ed25519Keypair.fromSecretKey(w(B(t)))}getKeyPair(t){return !t||!this.mnemonics?this.currentKeyPair:b(this.mnemonics,t)}getAddress(t){return !t||!this.mnemonics?this.currentAddress:b(this.mnemonics,t).getPublicKey().toSuiAddress()}switchAccount(t){this.mnemonics&&(this.currentKeyPair=b(this.mnemonics,t),this.currentAddress=this.currentKeyPair.getPublicKey().toSuiAddress());}};var ct=["u8","u16","u32","u64","u128","u256","bool","address"];function ut(r){if(!ct.includes(r))throw new Error(`Invalid SimpleBcsType: ${r}`);return {$kind:r}}var lt=r=>{if(typeof r=="string"&&isValidSuiObjectId(r))return "object";if(typeof r=="number"||typeof r=="bigint")return "u64";if(typeof r=="boolean")return "bool"};function U(r){return typeof r=="number"||typeof r=="bigint"||typeof r=="string"&&!isValidSuiAddress(r)&&!isNaN(Number(r))}function ht(r){return typeof r=="object"&&"vecType"in r&&"value"in r?!0:!!Array.isArray(r)}function dt(r){return typeof r=="object"&&"digest"in r&&"version"in r&&"objectId"in r}function mt(r){return typeof r=="object"&&"objectId"in r&&"initialSharedVersion"in r&&"mutable"in r}function E(r,t,e){if(t.length===0)throw new Error("Transaction builder error: Empty array is not allowed");let i=lt(t[0]),n=/^vector<(.+)>$/,s=/^([^:]+)::([^:]+)::([^<]+)(<(.+)>)?/;if(e=e||i,e==="object"){let o=t.map(a=>typeof a=="string"&&isValidSuiObjectId(a)?r.object(normalizeSuiObjectId(a)):d(r,a));return r.makeMoveVec({elements:o})}else if(typeof e=="string"&&!n.test(e)&&!s.test(e)){let o=ut(e),a=getPureBcsSchema(o);if(!a)throw new Error(`Unknown type: ${e}`);return r.pure(bcs.vector(a).serialize(t))}else {let o=t.map(a=>d(r,a));return r.makeMoveVec({elements:o,type:e})}}function y(r,t){return t.map(e=>e instanceof SerializedBcs||isSerializedBcs(e)?r.pure(e):ht(e)?"vecType"in e?E(r,e.value,e.vecType):E(r,e):U(e)?p(r,[e])[0]:d(r,e))}function g(r,t){return typeof t=="string"&&isValidSuiAddress(t)?r.pure.address(normalizeSuiAddress(t)):y(r,[t])[0]}function d(r,t){if(typeof t=="string")return r.object(t);if(dt(t))return r.objectRef(t);if(mt(t))return r.sharedObjectRef(t);if("Object"in t){if("ImmOrOwnedObject"in t.Object)return r.object(Inputs.ObjectRef(t.Object.ImmOrOwnedObject));if("SharedObject"in t.Object)return r.object(Inputs.SharedObjectRef(t.Object.SharedObject));throw new Error("Invalid argument type")}if(typeof t=="function"||"GasCoin"in t||"Input"in t||"Result"in t||"NestedResult"in t)return t;throw new Error("Invalid argument type")}function p(r,t){return t.map(e=>U(e)?r.pure.u64(e):y(r,[e])[0])}var V=(r,t)=>{let e=[];for(let i=0;i<r.length;i+=t)e.push(r.slice(i,i+t));return e};var u=class{txBlock;constructor(t){this.txBlock=t?Transaction.from(t):new Transaction;}get gas(){return this.txBlock.gas}getData(){return this.txBlock.getData()}address(t){return this.txBlock.pure.address(t)}get pure(){return this.txBlock.pure}object(t){return this.txBlock.object(t)}objectRef(t){return this.txBlock.objectRef(t)}sharedObjectRef(t){return this.txBlock.sharedObjectRef(t)}setSender(t){return this.txBlock.setSender(t)}setSenderIfNotSet(t){return this.txBlock.setSenderIfNotSet(t)}setExpiration(t){return this.txBlock.setExpiration(t)}setGasPrice(t){return this.txBlock.setGasPrice(t)}setGasBudget(t){return this.txBlock.setGasBudget(t)}setGasOwner(t){return this.txBlock.setGasOwner(t)}setGasPayment(t){return this.txBlock.setGasPayment(t)}serialize(){return this.txBlock.serialize()}toJSON(){return this.txBlock.toJSON()}sign(t){return this.txBlock.sign(t)}build(t={}){return this.txBlock.build(t)}getDigest(t={}){return this.txBlock.getDigest(t)}add(...t){return this.txBlock.add(...t)}publish({modules:t,dependencies:e}){return this.txBlock.publish({modules:t,dependencies:e})}upgrade(...t){return this.txBlock.upgrade(...t)}makeMoveVec(...t){return this.txBlock.makeMoveVec(...t)}transferObjects(t,e){return this.txBlock.transferObjects(t.map(i=>d(this.txBlock,i)),g(this.txBlock,e))}splitCoins(t,e){let i=this.txBlock.splitCoins(d(this.txBlock,t),p(this.txBlock,e));return e.map((n,s)=>i[s])}mergeCoins(t,e){let i=d(this.txBlock,t),n=e.map(s=>d(this.txBlock,s));return this.txBlock.mergeCoins(i,n)}moveCall(t,e=[],i=[]){let n=/(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;if(t.match(n)===null)throw new Error("Invalid target format. Expected `${string}::${string}::${string}`");let o=y(this.txBlock,e);return this.txBlock.moveCall({target:t,arguments:o,typeArguments:i})}transferSuiToMany(t,e){if(t.length!==e.length)throw new Error("transferSuiToMany: recipients.length !== amounts.length");let i=this.txBlock.splitCoins(this.txBlock.gas,p(this.txBlock,e));return t.map(s=>g(this.txBlock,s)).forEach((s,o)=>{this.txBlock.transferObjects([i[o]],s);}),this}transferSui(t,e){return this.transferSuiToMany([t],[e])}takeAmountFromCoins(t,e){let{splitedCoins:i,mergedCoin:n}=this.splitMultiCoins(t,p(this.txBlock,[e]));return [i,n]}splitSUIFromGas(t){return this.txBlock.splitCoins(this.txBlock.gas,p(this.txBlock,t))}splitMultiCoins(t,e){if(t.length===0)throw new Error("takeAmountFromCoins: coins array is empty");let i=V(t.slice(1),511),n=d(this.txBlock,t[0]);for(let o of i){let a=o.map(m=>d(this.txBlock,m));this.txBlock.mergeCoins(n,a);}return {splitedCoins:this.txBlock.splitCoins(n,p(this.txBlock,e)),mergedCoin:n}}transferCoinToMany(t,e,i,n){if(i.length!==n.length)throw new Error("transferCoinToMany: recipients.length !== amounts.length");let s=t.map(c=>d(this.txBlock,c)),{splitedCoins:o,mergedCoin:a}=this.splitMultiCoins(s,p(this.txBlock,n));return i.map(c=>g(this.txBlock,c)).forEach((c,h)=>{this.txBlock.transferObjects([o[h]],c);}),this.txBlock.transferObjects([a],g(this.txBlock,e)),this}transferCoin(t,e,i,n){return this.transferCoinToMany(t,e,[i],[n])}stakeSui(t,e){let[i]=this.txBlock.splitCoins(this.txBlock.gas,p(this.txBlock,[t]));return this.txBlock.moveCall({target:"0x3::sui_system::request_add_stake",arguments:y(this.txBlock,[this.txBlock.object(SUI_SYSTEM_STATE_OBJECT_ID),i,g(this.txBlock,e)])})}};var A=class{objectId;version;digest;constructor(t){this.objectId=t.objectId,this.version=t.version,this.digest=t.digest;}isFullObject(){return !!this.version&&!!this.digest}asCallArg(){return !this.version||!this.digest?this.objectId:{$kind:"Object",Object:{$kind:"ImmOrOwnedObject",ImmOrOwnedObject:{objectId:this.objectId,version:this.version,digest:this.digest}}}}updateFromTxResponse(t){let e=t.Transaction??t.FailedTransaction;if(!e)throw new Error("Bad transaction response!");let i=e.effects;if(!i)throw new Error("Transaction response has no effects!");for(let n of i.changedObjects)if(n.objectId===this.objectId&&n.outputDigest){this.digest=n.outputDigest,this.version=n.outputVersion??void 0;return}throw new Error("Could not find object in transaction response!")}};var x=class{objectId;initialSharedVersion;constructor(t){this.objectId=t.objectId,this.initialSharedVersion=t.initialSharedVersion;}asCallArg(t=!1){return this.initialSharedVersion?{$kind:"Object",Object:{$kind:"SharedObject",SharedObject:{objectId:this.objectId,initialSharedVersion:this.initialSharedVersion,mutable:t}}}:this.objectId}};var P=r=>new Promise(t=>setTimeout(t,r)),$=(r,t)=>{let e=[];for(let i=0;i<r.length;i+=t)e.push(r.slice(i,i+t));return e};var _=50;function k(r,t){return {baseUrl:r,network:t}}function T(r){switch(r){case"mainnet":return "https://fullnode.mainnet.sui.io:443";case"testnet":return "https://fullnode.testnet.sui.io:443";case"devnet":return "https://fullnode.devnet.sui.io:443";case"localnet":return "http://127.0.0.1:9000";default:throw new Error(`Unknown network: ${r}`)}}var f=class{clients=[];currentClient;fullNodes=[];network;constructor(t){this.network="mainnet","fullnodeUrls"in t&&t.fullnodeUrls?(this.network=t.network??"mainnet",this.fullNodes=t.fullnodeUrls,this.clients=this.fullNodes.map(e=>new SuiGrpcClient(k(e,this.network)))):"suiClients"in t&&t.suiClients?this.clients=t.suiClients:(this.fullNodes=[T(this.network)],this.clients=[new SuiGrpcClient(k(this.fullNodes[0],this.network))]),this.currentClient=this.clients[0];}switchToNextClient(){let t=this.clients.indexOf(this.currentClient);this.currentClient=this.clients[(t+1)%this.clients.length];}switchFullNodes(t,e){if(t.length===0)throw new Error("fullNodes cannot be empty");this.fullNodes=t,e&&(this.network=e),this.clients=t.map(i=>new SuiGrpcClient(k(i,this.network))),this.currentClient=this.clients[0];}get currentFullNode(){if(this.fullNodes.length===0)throw new Error("No full nodes available");let t=this.clients.indexOf(this.currentClient);if(t===-1)throw new Error("Current client not found");return this.fullNodes[t]}async sendTx(t,e){let i=typeof t=="string"?Uint8Array.from(Buffer.from(t,"base64")):t,n=Array.isArray(e)?e:[e];for(let s in this.clients)try{return await this.clients[s].core.executeTransaction({transaction:i,signatures:n,include:{balanceChanges:!0,effects:!0,events:!0,objectTypes:!0}})}catch(o){console.warn(`Failed to send transaction with fullnode ${this.fullNodes[s]}: ${o}`),await P(2e3);}throw new Error("Failed to send transaction with all fullnodes")}async dryRunTx(t){for(let e in this.clients)try{return await this.clients[e].core.simulateTransaction({transaction:t,include:{effects:!0,events:!0,balanceChanges:!0,commandResults:!0}})}catch(i){console.warn(`Failed to dry run transaction with fullnode ${this.fullNodes[e]}: ${i}`),await P(2e3);}throw new Error("Failed to dry run transaction with all fullnodes")}async getObjects(t,e){let i=e?.include??{content:!0,json:!0},n=$(t,Math.max(e?.batchSize??_,_)),s=[],o=null;for(let a of n){for(let m in this.clients)try{let h=(await this.clients[m].core.getObjects({objectIds:a,include:i})).objects.map(l=>l instanceof Error?null:l).filter(l=>l!==null);s.push(...h),o=null;break}catch(c){o=c instanceof Error?c:new Error(String(c)),await P(e?.switchClientDelay??2e3),console.warn(`Failed to get objects with fullnode ${this.fullNodes[m]}: ${c}`);}if(o)throw new Error(`Failed to get objects with all fullnodes: ${o}`)}return s}async getObject(t,e){return (await this.getObjects([t],e))[0]}async updateObjects(t){let e=t.map(n=>n.objectId),i=await this.getObjects(e);for(let n of i){let s=t.find(o=>o.objectId===n?.objectId);if(s instanceof x){let o=n.owner;o&&typeof o=="object"&&"Shared"in o?s.initialSharedVersion=o.Shared.initialSharedVersion:s.initialSharedVersion=void 0;}else s instanceof A&&(s.version=n?.version,s.digest=n?.digest);}}async selectCoins(t,e,i="0x2::SUI::SUI"){let n=[],s=0,o=!0,a=null;for(;o&&s<e;){let{objects:m,hasNextPage:c,cursor:h}=await this.currentClient.core.listCoins({owner:t,coinType:i,cursor:a});m.sort((l,W)=>parseInt(W.balance)-parseInt(l.balance));for(let l of m)if(n.push({objectId:l.objectId,digest:l.digest,version:l.version,balance:l.balance}),s=s+parseInt(l.balance),s>=e)break;a=h,o=c;}if(!n.length)throw new Error("No valid coins found for the transaction.");return n}};var v=class{accountManager;suiInteractor;constructor(t){let{mnemonics:e,secretKey:i,networkType:n}=t;this.accountManager=new S({mnemonics:e,secretKey:i});let s=n??"mainnet",o;"fullnodeUrls"in t?o={fullnodeUrls:t.fullnodeUrls,network:s}:"suiClients"in t?o={suiClients:t.suiClients}:o={fullnodeUrls:[T(s)],network:s},this.suiInteractor=new f(o);}createTxBlock(){let t=new u;return t.setSender(this.accountManager.currentAddress),t}getKeypair(t){return this.accountManager.getKeyPair(t)}switchAccount(t){this.accountManager.switchAccount(t);}getAddress(t){return this.accountManager.getAddress(t)}get currentAddress(){return this.accountManager.currentAddress}async getBalance(t,e){let i=this.accountManager.getAddress(e),{balance:n}=await this.suiInteractor.currentClient.core.getBalance({owner:i,coinType:t});return n}get client(){return this.suiInteractor.currentClient}async getObjects(t,e){return this.suiInteractor.getObjects(t,e)}async updateObjects(t){return this.suiInteractor.updateObjects(t)}async signTxn(t,e){t instanceof u&&t.setSender(this.getAddress(e));let i=t instanceof u?t.txBlock:t,n=i instanceof Uint8Array?i:await i.build({client:this.client});return await this.getKeypair(e).signTransaction(n)}async signAndSendTxn(t,e){let{bytes:i,signature:n}=await this.signTxn(t,e);return this.suiInteractor.sendTx(i,n)}async dryRunTxn(t,e){t instanceof u&&t.setSender(this.getAddress(e));let i=t instanceof u?t.txBlock:t,n=i instanceof Uint8Array?i:await i.build({client:this.client});return this.suiInteractor.dryRunTx(n)}async transferSui(t,e,i=!0,n){let s=new u;return s.transferSui(t,e),i?await this.signAndSendTxn(s,n):s}async transferSuiToMany(t,e,i=!0,n){let s=new u;return s.transferSuiToMany(t,e),i?await this.signAndSendTxn(s,n):s}async transferCoinToMany(t,e,i,n=!0,s){let o=new u,a=this.accountManager.getAddress(s),m=e.reduce((c,h)=>c+h,0);if(normalizeStructTag(i)===normalizeStructTag(SUI_TYPE_ARG))o.transferSuiToMany(t,e);else {let c=await this.suiInteractor.selectCoins(a,m,i);o.transferCoinToMany(c.map(h=>"objectId"in h?o.objectRef(h):h),a,t,e);}return n?await this.signAndSendTxn(o,s):o}async transferCoin(t,e,i,n=!0,s){return this.transferCoinToMany([t],[e],i,n,s)}async transferObjects(t,e,i=!0,n){let s=new u;return s.transferObjects(t,e),i?await this.signAndSendTxn(s,n):s}async moveCall(t){let{target:e,arguments:i=[],typeArguments:n=[],derivePathParams:s}=t,o=new u;return o.moveCall(e,i,n),this.signAndSendTxn(o,s)}async selectCoinsWithAmount(t,e,i){return i=i||this.accountManager.currentAddress,await this.suiInteractor.selectCoins(i,t,e)}async stakeSui(t,e,i=!0,n){let s=new u;return s.stakeSui(t,e),i?await this.signAndSendTxn(s,n):s}async inspectTxn(t,e){t instanceof u&&t.setSender(this.getAddress(e));let i=t instanceof u?t.txBlock:t,n=i instanceof Uint8Array?i:await i.build({client:this.client});return this.suiInteractor.currentClient.core.simulateTransaction({transaction:n,include:{effects:!0,events:!0,balanceChanges:!0,commandResults:!0}})}};function G(r){let t=fromBase64(r);if(t.length!==32&&t.length!==33)throw "invalid pubkey length";return t=t.length===33?t.slice(1):t,new Ed25519PublicKey(t)}var j=class r{pksWeightPairs;threshold;multiSigPublicKey;constructor(t,e){this.pksWeightPairs=t,this.threshold=e,this.multiSigPublicKey=MultiSigPublicKey.fromPublicKeys({threshold:this.threshold,publicKeys:this.pksWeightPairs});}static fromRawEd25519PublicKeys(t,e,i){let n=t.map((s,o)=>({publicKey:G(s),weight:e[o]}));return new r(n,i)}multiSigAddress(){return this.multiSigPublicKey.toSuiAddress()}combinePartialSigs(t){return this.multiSigPublicKey.combinePartialSignatures(t)}};
12
14
 
13
- var _=(r={})=>{let{accountIndex:t=0,isExternal:e=!1,addressIndex:i=0}=r;return `m/44'/784'/${t}'/${e?1:0}'/${i}'`},S=(r,t={})=>{let e=_(t);return ed25519.Ed25519Keypair.deriveKeypair(r,e)};var W=r=>/^0x[0-9a-fA-F]+$|^[0-9a-fA-F]+$/.test(r),Z=r=>/^[a-zA-Z0-9+/]+={0,2}$/g.test(r),B=r=>{if(W(r))return bcs.fromHex(r);if(Z(r))return bcs.fromBase64(r);throw new Error("The string is not a valid hex or base64 string.")},T=32,Y=64,O=r=>{if(r.length===Y)return r.slice(0,T);if(r.length===T+1&&r[0]===0)return r.slice(1);if(r.length===T)return r;throw new Error("invalid secret key")};var v=(r=24)=>bip39.generateMnemonic(english.wordlist,r===12?128:256);var f=class{constructor({mnemonics:t,secretKey:e}={}){this.mnemonics=t||"",this.secretKey=e||"",!this.mnemonics&&!this.secretKey&&(this.mnemonics=v(24)),this.currentKeyPair=this.secretKey?this.parseSecretKey(this.secretKey):S(this.mnemonics),this.currentAddress=this.currentKeyPair.getPublicKey().toSuiAddress();}parseSecretKey(t){if(t.startsWith(cryptography.SUI_PRIVATE_KEY_PREFIX)){let{secretKey:e}=cryptography.decodeSuiPrivateKey(t);return ed25519.Ed25519Keypair.fromSecretKey(O(e))}return ed25519.Ed25519Keypair.fromSecretKey(O(B(t)))}getKeyPair(t){return !t||!this.mnemonics?this.currentKeyPair:S(this.mnemonics,t)}getAddress(t){return !t||!this.mnemonics?this.currentAddress:S(this.mnemonics,t).getPublicKey().toSuiAddress()}switchAccount(t){this.mnemonics&&(this.currentKeyPair=S(this.mnemonics,t),this.currentAddress=this.currentKeyPair.getPublicKey().toSuiAddress());}};var nt=r=>{if(typeof r=="string"&&utils.isValidSuiObjectId(r))return "object";if(typeof r=="number"||typeof r=="bigint")return "u64";if(typeof r=="boolean")return "bool"};function E(r){return typeof r=="number"||typeof r=="bigint"||typeof r=="string"&&!utils.isValidSuiAddress(r)&&!isNaN(Number(r))}function st(r){return typeof r=="object"&&"vecType"in r&&"value"in r?!0:!!Array.isArray(r)}function ot(r){return typeof r=="object"&&"digest"in r&&"version"in r&&"objectId"in r}function at(r){return typeof r=="object"&&"objectId"in r&&"initialSharedVersion"in r&&"mutable"in r}function K(r,t,e){if(t.length===0)throw new Error("Transaction builder error: Empty array is not allowed");let i=nt(t[0]),n=/^vector<(.+)>$/,s=/^([^:]+)::([^:]+)::([^<]+)(<(.+)>)?/;if(e=e||i,e==="object"){let o=t.map(c=>typeof c=="string"&&utils.isValidSuiObjectId(c)?r.object(utils.normalizeSuiObjectId(c)):h(r,c));return r.makeMoveVec({elements:o})}else if(typeof e=="string"&&!n.test(e)&&!s.test(e)){let o=transactions.getPureBcsSchema(e);return r.pure(bcs.bcs.vector(o).serialize(t))}else {let o=t.map(c=>h(r,c));return r.makeMoveVec({elements:o,type:e})}}function y(r,t){return t.map(e=>e instanceof bcs.SerializedBcs||bcs.isSerializedBcs(e)?r.pure(e):st(e)?"vecType"in e?K(r,e.value,e.vecType):K(r,e):E(e)?d(r,[e])[0]:h(r,e))}function g(r,t){return typeof t=="string"&&utils.isValidSuiAddress(t)?r.pure.address(utils.normalizeSuiAddress(t)):y(r,[t])[0]}function h(r,t){if(typeof t=="string")return r.object(t);if(ot(t))return r.objectRef(t);if(at(t))return r.sharedObjectRef(t);if("Object"in t){if("ImmOrOwnedObject"in t.Object)return r.object(transactions.Inputs.ObjectRef(t.Object.ImmOrOwnedObject));if("SharedObject"in t.Object)return r.object(transactions.Inputs.SharedObjectRef(t.Object.SharedObject));throw new Error("Invalid argument type")}if(typeof t=="function"||"GasCoin"in t||"Input"in t||"Result"in t||"NestedResult"in t)return t;throw new Error("Invalid argument type")}function d(r,t){return t.map(e=>E(e)?r.pure.u64(e):y(r,[e])[0])}var M=(r,t)=>{let e=[];for(let i=0;i<r.length;i+=t)e.push(r.slice(i,i+t));return e};var u=class{constructor(t){this.txBlock=t?transactions.Transaction.from(t):new transactions.Transaction;}get gas(){return this.txBlock.gas}get blockData(){return this.txBlock.blockData}get getData(){return this.txBlock.getData()}address(t){return this.txBlock.pure.address(t)}get pure(){return this.txBlock.pure}object(t){return this.txBlock.object(t)}objectRef(t){return this.txBlock.objectRef(t)}sharedObjectRef(t){return this.txBlock.sharedObjectRef(t)}setSender(t){return this.txBlock.setSender(t)}setSenderIfNotSet(t){return this.txBlock.setSenderIfNotSet(t)}setExpiration(t){return this.txBlock.setExpiration(t)}setGasPrice(t){return this.txBlock.setGasPrice(t)}setGasBudget(t){return this.txBlock.setGasBudget(t)}setGasOwner(t){return this.txBlock.setGasOwner(t)}setGasPayment(t){return this.txBlock.setGasPayment(t)}serialize(){return this.txBlock.serialize()}toJSON(){return this.txBlock.toJSON()}sign(t){return this.txBlock.sign(t)}build(t={}){return this.txBlock.build(t)}getDigest(t={}){return this.txBlock.getDigest(t)}add(...t){return this.txBlock.add(...t)}publish({modules:t,dependencies:e}){return this.txBlock.publish({modules:t,dependencies:e})}upgrade(...t){return this.txBlock.upgrade(...t)}makeMoveVec(...t){return this.txBlock.makeMoveVec(...t)}transferObjects(t,e){return this.txBlock.transferObjects(t.map(i=>h(this.txBlock,i)),g(this.txBlock,e))}splitCoins(t,e){let i=this.txBlock.splitCoins(h(this.txBlock,t),d(this.txBlock,e));return e.map((n,s)=>i[s])}mergeCoins(t,e){let i=h(this.txBlock,t),n=e.map(s=>h(this.txBlock,s));return this.txBlock.mergeCoins(i,n)}moveCall(t,e=[],i=[]){let n=/(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;if(t.match(n)===null)throw new Error("Invalid target format. Expected `${string}::${string}::${string}`");let o=y(this.txBlock,e);return this.txBlock.moveCall({target:t,arguments:o,typeArguments:i})}transferSuiToMany(t,e){if(t.length!==e.length)throw new Error("transferSuiToMany: recipients.length !== amounts.length");let i=this.txBlock.splitCoins(this.txBlock.gas,d(this.txBlock,e));return t.map(s=>g(this.txBlock,s)).forEach((s,o)=>{this.txBlock.transferObjects([i[o]],s);}),this}transferSui(t,e){return this.transferSuiToMany([t],[e])}takeAmountFromCoins(t,e){let{splitedCoins:i,mergedCoin:n}=this.splitMultiCoins(t,d(this.txBlock,[e]));return [i,n]}splitSUIFromGas(t){return this.txBlock.splitCoins(this.txBlock.gas,d(this.txBlock,t))}splitMultiCoins(t,e){if(t.length===0)throw new Error("takeAmountFromCoins: coins array is empty");let i=M(t.slice(1),511),n=h(this.txBlock,t[0]);for(let o of i){let c=o.map(l=>h(this.txBlock,l));this.txBlock.mergeCoins(n,c);}return {splitedCoins:this.txBlock.splitCoins(n,d(this.txBlock,e)),mergedCoin:n}}transferCoinToMany(t,e,i,n){if(i.length!==n.length)throw new Error("transferSuiToMany: recipients.length !== amounts.length");let s=t.map(a=>h(this.txBlock,a)),{splitedCoins:o,mergedCoin:c}=this.splitMultiCoins(s,d(this.txBlock,n));return i.map(a=>g(this.txBlock,a)).forEach((a,m)=>{this.txBlock.transferObjects([o[m]],a);}),this.txBlock.transferObjects([c],g(this.txBlock,e)),this}transferCoin(t,e,i,n){return this.transferCoinToMany(t,e,[i],[n])}stakeSui(t,e){let[i]=this.txBlock.splitCoins(this.txBlock.gas,d(this.txBlock,[t]));return this.txBlock.moveCall({target:"0x3::sui_system::request_add_stake",arguments:y(this.txBlock,[this.txBlock.object(utils.SUI_SYSTEM_STATE_OBJECT_ID),i,g(this.txBlock,e)])})}};var A=class{constructor(t){this.objectId=t.objectId,this.version=t.version,this.digest=t.digest;}isFullObject(){return !!this.version&&!!this.digest}asCallArg(){return !this.version||!this.digest?this.objectId:{$kind:"Object",Object:{$kind:"ImmOrOwnedObject",ImmOrOwnedObject:{objectId:this.objectId,version:this.version,digest:this.digest}}}}updateFromTxResponse(t){let e=t.objectChanges;if(!e)throw new Error("Bad transaction response!");for(let i of e)if(i.type==="mutated"&&i.objectId===this.objectId){this.digest=i.digest,this.version=i.version;return}throw new Error("Could not find object in transaction response!")}};var x=class{constructor(t){this.objectId=t.objectId,this.initialSharedVersion=t.initialSharedVersion;}asCallArg(t=!1){return this.initialSharedVersion?{$kind:"Object",Object:{$kind:"SharedObject",SharedObject:{objectId:this.objectId,initialSharedVersion:this.initialSharedVersion,mutable:t}}}:this.objectId}};var P=r=>new Promise(t=>setTimeout(t,r)),U=(r,t)=>{let e=[];for(let i=0;i<r.length;i+=t)e.push(r.slice(i,i+t));return e};var b=class{constructor(t){this.clients=[];this.fullNodes=[];"fullnodeUrls"in t?(this.fullNodes=t.fullnodeUrls??[client.getFullnodeUrl("mainnet")],this.clients=this.fullNodes.map(e=>new client.SuiClient({url:e}))):"suiClients"in t&&t.suiClients?this.clients=t.suiClients:this.clients=[new client.SuiClient({url:client.getFullnodeUrl("mainnet")})],this.currentClient=this.clients[0];}switchToNextClient(){let t=this.clients.indexOf(this.currentClient);this.currentClient=this.clients[(t+1)%this.clients.length];}switchFullNodes(t){if(t.length===0)throw new Error("fullNodes cannot be empty");this.fullNodes=t,this.clients=t.map(e=>new client.SuiClient({url:e})),this.currentClient=this.clients[0];}get currentFullNode(){if(this.fullNodes.length===0)throw new Error("No full nodes available");let t=this.clients.indexOf(this.currentClient);if(t===-1)throw new Error("Current client not found");return this.fullNodes[t]}async sendTx(t,e){let i={showEvents:!0,showEffects:!0,showRawEffects:!0,showObjectChanges:!0,showBalanceChanges:!0};for(let n in this.clients)try{return await this.clients[n].executeTransactionBlock({transactionBlock:t,signature:e,options:i})}catch(s){console.warn(`Failed to send transaction with fullnode ${this.fullNodes[n]}: ${s}`),await P(2e3);}throw new Error("Failed to send transaction with all fullnodes")}async dryRunTx(t){for(let e in this.clients)try{return await this.clients[e].dryRunTransactionBlock({transactionBlock:t})}catch(i){console.warn(`Failed to dry run transaction with fullnode ${this.fullNodes[e]}: ${i}`),await P(2e3);}throw new Error("Failed to dry run transaction with all fullnodes")}async getObjects(t,e){let i=e??{showContent:!0,showDisplay:!0,showType:!0,showOwner:!0},n=U(t,Math.max(e?.batchSize??50,50)),s=[],o=null;for(let c of n){for(let l in this.clients)try{let m=(await this.clients[l].multiGetObjects({ids:c,options:i})).map(p=>p.data).filter(p=>p!=null);s.push(...m),o=null;break}catch(a){o=a instanceof Error?a:new Error(String(a)),await P(e?.switchClientDelay??2e3),console.warn(`Failed to get objects with fullnode ${this.fullNodes[l]}: ${a}`);}if(o)throw new Error(`Failed to get objects with all fullnodes: ${o}`)}return s}async getObject(t,e){return (await this.getObjects([t],e))[0]}async updateObjects(t){let e=t.map(n=>n.objectId),i=await this.getObjects(e);for(let n of i){let s=t.find(o=>o.objectId===n?.objectId);s instanceof x?n.owner&&typeof n.owner=="object"&&"Shared"in n.owner?s.initialSharedVersion=n.owner.Shared.initial_shared_version:s.initialSharedVersion=void 0:s instanceof A&&(s.version=n?.version,s.digest=n?.digest);}}async selectCoins(t,e,i="0x2::SUI::SUI"){let n=[],s=0,o=!0,c=null;for(;o&&s<e;){let l=await this.currentClient.getCoins({owner:t,coinType:i,cursor:c});l.data.sort((a,m)=>parseInt(m.balance)-parseInt(a.balance));for(let a of l.data)if(n.push({objectId:a.coinObjectId,digest:a.digest,version:a.version,balance:a.balance}),s=s+parseInt(a.balance),s>=e)break;c=l.nextCursor,o=l.hasNextPage;}if(!n.length)throw new Error("No valid coins found for the transaction.");return n}};var k=class{constructor(t){let{mnemonics:e,secretKey:i,networkType:n}=t;this.accountManager=new f({mnemonics:e,secretKey:i});let s;"fullnodeUrls"in t?s={fullnodeUrls:t.fullnodeUrls}:"suiClients"in t?s={suiClients:t.suiClients}:s={fullnodeUrls:[client.getFullnodeUrl(n??"mainnet")]},this.suiInteractor=new b(s);}createTxBlock(){let t=new u;return t.setSender(this.accountManager.currentAddress),t}getKeypair(t){return this.accountManager.getKeyPair(t)}switchAccount(t){this.accountManager.switchAccount(t);}getAddress(t){return this.accountManager.getAddress(t)}get currentAddress(){return this.accountManager.currentAddress}async getBalance(t,e){let i=this.accountManager.getAddress(e);return this.suiInteractor.currentClient.getBalance({owner:i,coinType:t})}get client(){return this.suiInteractor.currentClient}async getObjects(t,e){return this.suiInteractor.getObjects(t,e)}async updateObjects(t){return this.suiInteractor.updateObjects(t)}async signTxn(t,e){t instanceof u&&t.setSender(this.getAddress(e));let i=t instanceof u?t.txBlock:t,n=i instanceof Uint8Array?i:await i.build({client:this.client});return await this.getKeypair(e).signTransaction(n)}async signAndSendTxn(t,e){let{bytes:i,signature:n}=await this.signTxn(t,e);return this.suiInteractor.sendTx(i,n)}async dryRunTxn(t,e){t instanceof u&&t.setSender(this.getAddress(e));let i=t instanceof u?t.txBlock:t,n=i instanceof Uint8Array?i:await i.build({client:this.client});return this.suiInteractor.dryRunTx(n)}async transferSui(t,e,i=!0,n){let s=new u;return s.transferSui(t,e),i?await this.signAndSendTxn(s,n):s}async transferSuiToMany(t,e,i=!0,n){let s=new u;return s.transferSuiToMany(t,e),i?await this.signAndSendTxn(s,n):s}async transferCoinToMany(t,e,i,n=!0,s){let o=new u,c=this.accountManager.getAddress(s),l=e.reduce((m,p)=>m+p,0),a=await this.suiInteractor.selectCoins(c,l,i);return o.transferCoinToMany(a.map(m=>m.objectId),c,t,e),n?await this.signAndSendTxn(o,s):o}async transferCoin(t,e,i,n=!0,s){return this.transferCoinToMany([t],[e],i,n,s)}async transferObjects(t,e,i=!0,n){let s=new u;return s.transferObjects(t,e),i?await this.signAndSendTxn(s,n):s}async moveCall(t){let{target:e,arguments:i=[],typeArguments:n=[],derivePathParams:s}=t,o=new u;return o.moveCall(e,i,n),this.signAndSendTxn(o,s)}async selectCoinsWithAmount(t,e,i){return i=i||this.accountManager.currentAddress,await this.suiInteractor.selectCoins(i,t,e)}async stakeSui(t,e,i=!0,n){let s=new u;return s.stakeSui(t,e),i?await this.signAndSendTxn(s,n):s}async inspectTxn(t,e){let i=t instanceof u?t.txBlock:t;return this.suiInteractor.currentClient.devInspectTransactionBlock({transactionBlock:i,sender:this.getAddress(e)})}};function N(r){let t=bcs.fromBase64(r);if(t.length!==32&&t.length!==33)throw "invalid pubkey length";return t=t.length===33?t.slice(1):t,new ed25519.Ed25519PublicKey(t)}var j=class r{constructor(t,e){this.pksWeightPairs=t,this.threshold=e,this.multiSigPublicKey=multisig.MultiSigPublicKey.fromPublicKeys({threshold:this.threshold,publicKeys:this.pksWeightPairs});}static fromRawEd25519PublicKeys(t,e,i){let n=t.map((s,o)=>({publicKey:N(s),weight:e[o]}));return new r(n,i)}multiSigAddress(){return this.multiSigPublicKey.toSuiAddress()}combinePartialSigs(t){return this.multiSigPublicKey.combinePartialSignatures(t)}};
14
-
15
- exports.MultiSigClient = j;
16
- exports.SuiAccountManager = f;
17
- exports.SuiInteractor = b;
18
- exports.SuiKit = k;
19
- exports.SuiTxBlock = u;
20
- Object.keys(utils).forEach(function (k) {
21
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
22
- enumerable: true,
23
- get: function () { return utils[k]; }
24
- });
25
- });
26
- Object.keys(transactions).forEach(function (k) {
27
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
28
- enumerable: true,
29
- get: function () { return transactions[k]; }
30
- });
31
- });
15
+ export { j as MultiSigClient, S as SuiAccountManager, f as SuiInteractor, v as SuiKit, u as SuiTxBlock, T as getFullnodeUrl };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scallop-io/sui-kit",
3
- "version": "1.4.3",
3
+ "version": "2.0.0",
4
4
  "description": "Toolkit for interacting with SUI network",
5
5
  "keywords": [
6
6
  "sui",
@@ -21,16 +21,15 @@
21
21
  "access": "public"
22
22
  },
23
23
  "engines": {
24
- "node": ">=16"
24
+ "node": ">=22"
25
25
  },
26
+ "type": "module",
26
27
  "main": "./dist/index.js",
27
- "module": "./dist/index.mjs",
28
28
  "types": "./dist/index.d.ts",
29
29
  "exports": {
30
30
  ".": {
31
- "source": "./src/index.ts",
32
- "import": "./dist/index.mjs",
33
- "require": "./dist/index.js"
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
34
33
  }
35
34
  },
36
35
  "files": [
@@ -38,8 +37,8 @@
38
37
  "src"
39
38
  ],
40
39
  "dependencies": {
41
- "@mysten/bcs": "^1.6.0",
42
- "@mysten/sui": "^1.28.2",
40
+ "@mysten/bcs": "^2.0.0",
41
+ "@mysten/sui": "^2.0.0",
43
42
  "@scure/bip39": "^1.5.4",
44
43
  "assert": "^2.1.0",
45
44
  "bech32": "^2.0.0"
@@ -48,6 +47,8 @@
48
47
  "@commitlint/cli": "^18.0.0",
49
48
  "@commitlint/config-conventional": "^18.0.0",
50
49
  "@commitlint/prompt-cli": "^18.0.0",
50
+ "@protobuf-ts/grpcweb-transport": "^2.11.1",
51
+ "@protobuf-ts/runtime-rpc": "^2.11.1",
51
52
  "@types/node": "^20.8.7",
52
53
  "@types/tmp": "^0.2.5",
53
54
  "@typescript-eslint/eslint-plugin": "^8.11.0",
@@ -135,12 +136,12 @@
135
136
  },
136
137
  "scripts": {
137
138
  "clean": "rm -rf tsconfig.tsbuildinfo ./dist",
138
- "build": "npm run build:types && npm run build:tsup",
139
- "build:tsup": "tsup ./src/index.ts --format esm,cjs --splitting --minify --treeshake",
139
+ "build": "npm run build:types && npm run build:prod",
140
+ "build:prod": "tsup --env.NODE_ENV production",
141
+ "build:dev": "tsup",
140
142
  "build:types": "tsc --build",
141
- "watch:tsup": "tsup ./src/index.ts --format esm,cjs --clean --splitting --watch",
142
- "watch:types": "tsc --watch",
143
- "watch": "pnpm run clean & pnpm run watch:types & pnpm run watch:tsup",
143
+ "watch:tsup": "tsup --watch",
144
+ "watch": "pnpm run clean && pnpm run watch:tsup",
144
145
  "test": "pnpm test:typecheck && pnpm test:unit && pnpm test:integration",
145
146
  "test:typecheck": "tsc -p ./test",
146
147
  "test:unit": "vitest run test/unit --test-timeout=60000",
package/src/index.ts CHANGED
@@ -1,8 +1,12 @@
1
1
  export * from '@mysten/sui/utils';
2
2
  export * from '@mysten/sui/transactions';
3
- export { SuiKit } from './suiKit';
4
- export { SuiAccountManager } from './libs/suiAccountManager';
5
- export { SuiTxBlock } from './libs/suiTxBuilder';
6
- export { MultiSigClient } from './libs/multiSig';
7
- export { SuiInteractor } from './libs/suiInteractor';
8
- export type * from './types';
3
+ export { SuiKit } from './suiKit.js';
4
+ export { SuiAccountManager } from './libs/suiAccountManager/index.js';
5
+ export { SuiTxBlock } from './libs/suiTxBuilder/index.js';
6
+ export { MultiSigClient } from './libs/multiSig/index.js';
7
+ export {
8
+ SuiInteractor,
9
+ getFullnodeUrl,
10
+ type SimulateTransactionResponse,
11
+ } from './libs/suiInteractor/index.js';
12
+ export type * from './types/index.js';
@@ -1,6 +1,6 @@
1
1
  import { MultiSigPublicKey } from '@mysten/sui/multisig';
2
2
  import type { PublicKey } from '@mysten/sui/cryptography';
3
- import { ed25519PublicKeyFromBase64 } from './publickey';
3
+ import { ed25519PublicKeyFromBase64 } from './publickey.js';
4
4
 
5
5
  export type PublicKeyWeightPair = {
6
6
  publicKey: PublicKey;
@@ -1 +1 @@
1
- export { MultiSigClient } from './client';
1
+ export { MultiSigClient } from './client.js';
@@ -1,8 +1,11 @@
1
1
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
2
- import { getKeyPair } from './keypair';
3
- import { hexOrBase64ToUint8Array, normalizePrivateKey } from './util';
4
- import { generateMnemonic } from './crypto';
5
- import type { AccountManagerParams, DerivePathParams } from 'src/types';
2
+ import { getKeyPair } from './keypair.js';
3
+ import { hexOrBase64ToUint8Array, normalizePrivateKey } from './util.js';
4
+ import { generateMnemonic } from './crypto.js';
5
+ import type {
6
+ AccountManagerParams,
7
+ DerivePathParams,
8
+ } from '../../types/index.js';
6
9
  import {
7
10
  SUI_PRIVATE_KEY_PREFIX,
8
11
  decodeSuiPrivateKey,
@@ -1,5 +1,5 @@
1
1
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
2
- import type { DerivePathParams } from 'src/types';
2
+ import type { DerivePathParams } from '../../types/index.js';
3
3
 
4
4
  /**
5
5
  * @description Get ed25519 derive path for SUI
@@ -1 +1,7 @@
1
- export { SuiInteractor } from './suiInteractor';
1
+ export {
2
+ SuiInteractor,
3
+ getFullnodeUrl,
4
+ type SuiObjectData,
5
+ type SuiObjectDataOptions,
6
+ type SimulateTransactionResponse,
7
+ } from './suiInteractor.js';
@@ -1,32 +1,81 @@
1
- import { SuiInteractorParams } from 'src/types';
2
- import { SuiOwnedObject, SuiSharedObject } from '../suiModel';
3
- import { batch, delay } from './util';
4
- import {
5
- type SuiTransactionBlockResponseOptions,
6
- type SuiTransactionBlockResponse,
7
- type SuiObjectDataOptions,
8
- type SuiObjectData,
9
- type DryRunTransactionBlockResponse,
10
- SuiClient,
11
- getFullnodeUrl,
12
- } from '@mysten/sui/client';
1
+ import { SuiInteractorParams, NetworkType } from '../../types/index.js';
2
+ import { SuiOwnedObject, SuiSharedObject } from '../suiModel/index.js';
3
+ import { batch, delay } from './util.js';
4
+ import { SuiGrpcClient, type SuiGrpcClientOptions } from '@mysten/sui/grpc';
5
+ import type { ClientWithCoreApi, SuiClientTypes } from '@mysten/sui/client';
6
+
7
+ const MAX_OBJECTS_PER_REQUEST = 50;
8
+
9
+ // Helper to create gRPC client options with baseUrl
10
+ function createGrpcClientOptions(
11
+ url: string,
12
+ network: NetworkType
13
+ ): SuiGrpcClientOptions {
14
+ return { baseUrl: url, network } satisfies SuiGrpcClientOptions;
15
+ }
16
+
17
+ // Helper to get fullnode URLs for each network
18
+ function getFullnodeUrl(network: NetworkType): string {
19
+ switch (network) {
20
+ case 'mainnet':
21
+ return 'https://fullnode.mainnet.sui.io:443';
22
+ case 'testnet':
23
+ return 'https://fullnode.testnet.sui.io:443';
24
+ case 'devnet':
25
+ return 'https://fullnode.devnet.sui.io:443';
26
+ case 'localnet':
27
+ return 'http://127.0.0.1:9000';
28
+ default:
29
+ throw new Error(`Unknown network: ${network}`);
30
+ }
31
+ }
32
+
33
+ // Object data type from SDK v2
34
+ export type SuiObjectData = SuiClientTypes.Object<{
35
+ content: true;
36
+ json: true;
37
+ }>;
38
+
39
+ // Options for getObjects (SDK v2 naming)
40
+ export type SuiObjectDataOptions = SuiClientTypes.ObjectInclude;
41
+
42
+ // Simulate transaction response type
43
+ export type SimulateTransactionResponse =
44
+ SuiClientTypes.SimulateTransactionResult<{
45
+ effects: true;
46
+ events: true;
47
+ balanceChanges: true;
48
+ commandResults: true;
49
+ }>;
13
50
 
14
51
  /**
15
52
  * Encapsulates all functions that interact with the sui sdk
16
53
  */
17
54
  export class SuiInteractor {
18
- private clients: SuiClient[] = [];
19
- public currentClient: SuiClient;
55
+ private clients: ClientWithCoreApi[] = [];
56
+ public currentClient: ClientWithCoreApi;
20
57
  private fullNodes: string[] = [];
58
+ private network: NetworkType;
21
59
 
22
60
  constructor(params: Partial<SuiInteractorParams>) {
23
- if ('fullnodeUrls' in params) {
24
- this.fullNodes = params.fullnodeUrls ?? [getFullnodeUrl('mainnet')];
25
- this.clients = this.fullNodes.map((url) => new SuiClient({ url }));
61
+ // Default network
62
+ this.network = 'mainnet';
63
+
64
+ if ('fullnodeUrls' in params && params.fullnodeUrls) {
65
+ this.network = params.network ?? 'mainnet';
66
+ this.fullNodes = params.fullnodeUrls;
67
+ this.clients = this.fullNodes.map(
68
+ (url) => new SuiGrpcClient(createGrpcClientOptions(url, this.network))
69
+ );
26
70
  } else if ('suiClients' in params && params.suiClients) {
27
71
  this.clients = params.suiClients;
28
72
  } else {
29
- this.clients = [new SuiClient({ url: getFullnodeUrl('mainnet') })];
73
+ this.fullNodes = [getFullnodeUrl(this.network)];
74
+ this.clients = [
75
+ new SuiGrpcClient(
76
+ createGrpcClientOptions(this.fullNodes[0], this.network)
77
+ ),
78
+ ];
30
79
  }
31
80
  this.currentClient = this.clients[0];
32
81
  }
@@ -37,12 +86,17 @@ export class SuiInteractor {
37
86
  this.clients[(currentClientIdx + 1) % this.clients.length];
38
87
  }
39
88
 
40
- switchFullNodes(fullNodes: string[]) {
89
+ switchFullNodes(fullNodes: string[], network?: NetworkType) {
41
90
  if (fullNodes.length === 0) {
42
91
  throw new Error('fullNodes cannot be empty');
43
92
  }
44
93
  this.fullNodes = fullNodes;
45
- this.clients = fullNodes.map((url) => new SuiClient({ url }));
94
+ if (network) {
95
+ this.network = network;
96
+ }
97
+ this.clients = fullNodes.map(
98
+ (url) => new SuiGrpcClient(createGrpcClientOptions(url, this.network))
99
+ );
46
100
  this.currentClient = this.clients[0];
47
101
  }
48
102
 
@@ -62,21 +116,32 @@ export class SuiInteractor {
62
116
  async sendTx(
63
117
  transactionBlock: Uint8Array | string,
64
118
  signature: string | string[]
65
- ): Promise<SuiTransactionBlockResponse> {
66
- const txResOptions: SuiTransactionBlockResponseOptions = {
67
- showEvents: true,
68
- showEffects: true,
69
- showRawEffects: true,
70
- showObjectChanges: true,
71
- showBalanceChanges: true,
72
- };
119
+ ): Promise<
120
+ SuiClientTypes.TransactionResult<{
121
+ balanceChanges: true;
122
+ effects: true;
123
+ events: true;
124
+ objectTypes: true;
125
+ }>
126
+ > {
127
+ const txBytes =
128
+ typeof transactionBlock === 'string'
129
+ ? Uint8Array.from(Buffer.from(transactionBlock, 'base64'))
130
+ : transactionBlock;
131
+
132
+ const signatures = Array.isArray(signature) ? signature : [signature];
73
133
 
74
134
  for (const clientIdx in this.clients) {
75
135
  try {
76
- return await this.clients[clientIdx].executeTransactionBlock({
77
- transactionBlock,
78
- signature,
79
- options: txResOptions,
136
+ return await this.clients[clientIdx].core.executeTransaction({
137
+ transaction: txBytes,
138
+ signatures,
139
+ include: {
140
+ balanceChanges: true,
141
+ effects: true,
142
+ events: true,
143
+ objectTypes: true,
144
+ },
80
145
  });
81
146
  } catch (err) {
82
147
  console.warn(
@@ -90,11 +155,17 @@ export class SuiInteractor {
90
155
 
91
156
  async dryRunTx(
92
157
  transactionBlock: Uint8Array
93
- ): Promise<DryRunTransactionBlockResponse> {
158
+ ): Promise<SimulateTransactionResponse> {
94
159
  for (const clientIdx in this.clients) {
95
160
  try {
96
- return await this.clients[clientIdx].dryRunTransactionBlock({
97
- transactionBlock,
161
+ return await this.clients[clientIdx].core.simulateTransaction({
162
+ transaction: transactionBlock,
163
+ include: {
164
+ effects: true,
165
+ events: true,
166
+ balanceChanges: true,
167
+ commandResults: true,
168
+ },
98
169
  });
99
170
  } catch (err) {
100
171
  console.warn(
@@ -108,35 +179,42 @@ export class SuiInteractor {
108
179
 
109
180
  async getObjects(
110
181
  ids: string[],
111
- options?: SuiObjectDataOptions & {
182
+ options?: {
183
+ include?: SuiObjectDataOptions;
112
184
  batchSize?: number;
113
185
  switchClientDelay?: number;
114
186
  }
115
187
  ): Promise<SuiObjectData[]> {
116
- const opts: SuiObjectDataOptions = options ?? {
117
- showContent: true,
118
- showDisplay: true,
119
- showType: true,
120
- showOwner: true,
121
- };
122
-
123
- const batchIds = batch(ids, Math.max(options?.batchSize ?? 50, 50));
188
+ const include = options?.include ?? { content: true, json: true };
189
+
190
+ const batchIds = batch(
191
+ ids,
192
+ Math.max(
193
+ options?.batchSize ?? MAX_OBJECTS_PER_REQUEST,
194
+ MAX_OBJECTS_PER_REQUEST
195
+ )
196
+ );
124
197
  const results: SuiObjectData[] = [];
125
198
  let lastError = null;
126
199
 
127
- for (const batch of batchIds) {
200
+ for (const batchChunk of batchIds) {
128
201
  for (const clientIdx in this.clients) {
129
202
  try {
130
- const objects = await this.clients[clientIdx].multiGetObjects({
131
- ids: batch,
132
- options: opts,
203
+ const response = await this.clients[clientIdx].core.getObjects({
204
+ objectIds: batchChunk,
205
+ include,
133
206
  });
134
- const parsedObjects = objects
135
- .map((object) => {
136
- return object.data;
207
+
208
+ const parsedObjects = response.objects
209
+ .map((obj) => {
210
+ if (obj instanceof Error) {
211
+ return null;
212
+ }
213
+ return obj as SuiObjectData;
137
214
  })
138
- .filter((object) => object !== null && object !== undefined);
139
- results.push(...(parsedObjects as SuiObjectData[]));
215
+ .filter((object): object is SuiObjectData => object !== null);
216
+
217
+ results.push(...parsedObjects);
140
218
  lastError = null;
141
219
  break; // Exit the client loop if successful
142
220
  } catch (err) {
@@ -157,7 +235,7 @@ export class SuiInteractor {
157
235
  return results;
158
236
  }
159
237
 
160
- async getObject(id: string, options?: SuiObjectDataOptions) {
238
+ async getObject(id: string, options?: { include?: SuiObjectDataOptions }) {
161
239
  const objects = await this.getObjects([id], options);
162
240
  return objects[0];
163
241
  }
@@ -174,13 +252,11 @@ export class SuiInteractor {
174
252
  (obj) => obj.objectId === object?.objectId
175
253
  );
176
254
  if (suiObject instanceof SuiSharedObject) {
177
- if (
178
- object.owner &&
179
- typeof object.owner === 'object' &&
180
- 'Shared' in object.owner
181
- ) {
182
- suiObject.initialSharedVersion =
183
- object.owner.Shared.initial_shared_version;
255
+ const owner = object.owner;
256
+ if (owner && typeof owner === 'object' && 'Shared' in owner) {
257
+ suiObject.initialSharedVersion = (
258
+ owner as { Shared: { initialSharedVersion: string } }
259
+ ).Shared.initialSharedVersion;
184
260
  } else {
185
261
  suiObject.initialSharedVersion = undefined;
186
262
  }
@@ -212,16 +288,17 @@ export class SuiInteractor {
212
288
  let hasNext = true,
213
289
  nextCursor: string | null | undefined = null;
214
290
  while (hasNext && totalAmount < amount) {
215
- const coins = await this.currentClient.getCoins({
216
- owner: addr,
217
- coinType: coinType,
218
- cursor: nextCursor,
219
- });
291
+ const { objects, hasNextPage, cursor } =
292
+ await this.currentClient.core.listCoins({
293
+ owner: addr,
294
+ coinType: coinType,
295
+ cursor: nextCursor,
296
+ });
220
297
  // Sort the coins by balance in descending order
221
- coins.data.sort((a, b) => parseInt(b.balance) - parseInt(a.balance));
222
- for (const coinData of coins.data) {
298
+ objects.sort((a, b) => parseInt(b.balance) - parseInt(a.balance));
299
+ for (const coinData of objects) {
223
300
  selectedCoins.push({
224
- objectId: coinData.coinObjectId,
301
+ objectId: coinData.objectId,
225
302
  digest: coinData.digest,
226
303
  version: coinData.version,
227
304
  balance: coinData.balance,
@@ -232,8 +309,8 @@ export class SuiInteractor {
232
309
  }
233
310
  }
234
311
 
235
- nextCursor = coins.nextCursor;
236
- hasNext = coins.hasNextPage;
312
+ nextCursor = cursor;
313
+ hasNext = hasNextPage;
237
314
  }
238
315
 
239
316
  if (!selectedCoins.length) {
@@ -242,3 +319,5 @@ export class SuiInteractor {
242
319
  return selectedCoins;
243
320
  }
244
321
  }
322
+
323
+ export { getFullnodeUrl };
@@ -1,2 +1,2 @@
1
- export { SuiOwnedObject } from './suiOwnedObject';
2
- export { SuiSharedObject } from './suiSharedObject';
1
+ export { SuiOwnedObject } from './suiOwnedObject.js';
2
+ export { SuiSharedObject } from './suiSharedObject.js';
@@ -1,7 +1,12 @@
1
1
  // TODO: I think we can remove this file or update to NormalizedCallArg
2
- import type { SuiTransactionBlockResponse } from '@mysten/sui/client';
2
+ import type { SuiClientTypes } from '@mysten/sui/client';
3
3
  import type { CallArg } from '@mysten/sui/transactions';
4
4
 
5
+ // Transaction result type with effects
6
+ type TransactionResultWithEffects = SuiClientTypes.TransactionResult<{
7
+ effects: true;
8
+ }>;
9
+
5
10
  export class SuiOwnedObject {
6
11
  public readonly objectId: string;
7
12
  public version?: string;
@@ -43,15 +48,19 @@ export class SuiOwnedObject {
43
48
  * Update object version & digest based on the transaction response.
44
49
  * @param txResponse
45
50
  */
46
- updateFromTxResponse(txResponse: SuiTransactionBlockResponse) {
47
- const changes = txResponse.objectChanges;
48
- if (!changes) {
51
+ updateFromTxResponse(txResponse: TransactionResultWithEffects) {
52
+ const tx = txResponse.Transaction ?? txResponse.FailedTransaction;
53
+ if (!tx) {
49
54
  throw new Error('Bad transaction response!');
50
55
  }
51
- for (const change of changes) {
52
- if (change.type === 'mutated' && change.objectId === this.objectId) {
53
- this.digest = change.digest;
54
- this.version = change.version;
56
+ const effects = tx.effects;
57
+ if (!effects) {
58
+ throw new Error('Transaction response has no effects!');
59
+ }
60
+ for (const change of effects.changedObjects) {
61
+ if (change.objectId === this.objectId && change.outputDigest) {
62
+ this.digest = change.outputDigest;
63
+ this.version = change.outputVersion ?? undefined;
55
64
  return;
56
65
  }
57
66
  }