@msafe/sui3-sdk 0.0.11 → 0.0.12-pre-84adfec.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.
@@ -1,14 +1,21 @@
1
- import { MSafeAccountInfo, MultisigAccountManager } from '@msafe/sui3-utils';
1
+ import {
2
+ buildIntentionTransaction,
3
+ getIntentionType,
4
+ MSafeAccountInfo,
5
+ MultisigAccountManager,
6
+ } from '@msafe/sui3-utils';
2
7
  import { SuiObjectData } from '@mysten/sui.js/client';
3
8
  import { SerializedSignature } from '@mysten/sui.js/cryptography';
9
+ import { SuiObjectResponse } from '@mysten/sui.js/src/client';
4
10
  import { normalizeStructTag } from '@mysten/sui.js/utils';
5
11
 
6
12
  import { MessageHelper } from '@/core/MessageHelper';
13
+ import { MSAFE_APPLICATION } from '@/globals';
7
14
  import { MSafeGlobals } from '@/globals/MSafeGlobals';
8
15
  import { IntentionHelper, TxIntention } from '@/transactions/intention';
9
16
  import { OwnedCoin } from '@/types/assets';
10
17
  import { PaginationOption } from '@/types/backend';
11
- import { PendingTx } from '@/types/msafe';
18
+ import { PendingTx, SimulationResult } from '@/types/msafe';
12
19
  import { CoinHelper } from '@/utils';
13
20
  import { HexToUint8Array } from '@/utils/buffer';
14
21
  import { BatchObjectOptions, getAllOwnedObjects } from '@/utils/iter/object';
@@ -53,11 +60,11 @@ export class MSafeAccount {
53
60
  }
54
61
 
55
62
  async ownedObjects(options?: BatchObjectOptions): Promise<SuiObjectData[]> {
56
- return getAllOwnedObjects(this.suiClient, this.address, options);
57
- }
58
-
59
- async pendingTransactions() {
60
- return this.backend.getPendingTransactions(this.address);
63
+ const filterCoinObjectOptions = {
64
+ filter: (objRes: SuiObjectResponse) => !objRes?.data?.type?.startsWith('0x2::coin::Coin'),
65
+ ...options,
66
+ };
67
+ return getAllOwnedObjects(this.suiClient, this.address, filterCoinObjectOptions);
61
68
  }
62
69
 
63
70
  async pendingTransaction(): Promise<PendingTx | undefined> {
@@ -68,21 +75,20 @@ export class MSafeAccount {
68
75
  if (pendings.length === 0) {
69
76
  return undefined;
70
77
  }
71
- if (pendings.length === 1) {
72
- return pendings[0];
73
- }
74
78
 
75
- const [rejectPending, pendingTx] = pendings[0].isRejectTx ? [pendings[0], pendings[1]] : [pendings[1], pendings[0]];
76
- pendingTx.rejectDigest = rejectPending.digest;
77
- pendingTx.rejectPayload = rejectPending.payload;
78
- pendingTx.rejectVotes = rejectPending.votes;
79
+ const pendingTx = pendings.find((tx) => !tx.isRejectTx);
80
+ const rejectPending = pendings.find((tx) => tx.isRejectTx);
79
81
 
80
- return pendingTx;
82
+ return {
83
+ ...pendingTx!,
84
+ rejectDigest: rejectPending?.digest ?? '',
85
+ rejectPayload: rejectPending?.payload ?? '',
86
+ rejectVotes: rejectPending?.votes ?? [],
87
+ };
81
88
  }
82
89
 
83
90
  async historyTransaction(paginationOption?: PaginationOption) {
84
- const paginatedHistoryTransactions = await this.backend.getHistoryTransactions(this.address, paginationOption);
85
- return paginatedHistoryTransactions.data;
91
+ return this.backend.getHistoryTransactions(this.address, paginationOption);
86
92
  }
87
93
 
88
94
  async futureIntentions(paginationOption?: PaginationOption) {
@@ -99,16 +105,26 @@ export class MSafeAccount {
99
105
  }
100
106
 
101
107
  async proposeIntention(intention: TxIntention, sequenceNumber: number) {
102
- const message = MessageHelper.proposeIntentionMessage({ intention, sn: sequenceNumber });
108
+ const message = MessageHelper.proposeIntentionMessage({
109
+ intention,
110
+ sn: sequenceNumber,
111
+ msafeAddress: this.address,
112
+ });
103
113
  const signature = await this.wallet.signPersonalMessage({
104
114
  messageStr: message,
105
115
  });
116
+
117
+ const txType = getIntentionType(intention);
118
+ // TODO get application from common utils
106
119
  await this.backend.proposeIntention({
107
120
  intention,
108
121
  sequenceNumber,
109
122
  msafeAddress: this.address,
110
123
  userAddress: await this.userAddress(),
111
124
  signature: signature.signature,
125
+ application: MSAFE_APPLICATION,
126
+ txType: txType.txType,
127
+ txSubType: txType.txSubType,
112
128
  });
113
129
  }
114
130
 
@@ -152,7 +168,7 @@ export class MSafeAccount {
152
168
  payloadToReject = pending.payload;
153
169
  } else {
154
170
  const pendingTx = await this.pendingTransaction();
155
- if (!pendingTx || pendingTx?.rejectDigest !== undefined) {
171
+ if (!pendingTx || pendingTx.rejectDigest !== '') {
156
172
  throw new Error('Already rejected');
157
173
  }
158
174
 
@@ -181,6 +197,29 @@ export class MSafeAccount {
181
197
  return this.backend.skipNextFailedIntention({ msafeAddress: this.address, userAddress: await this.userAddress() });
182
198
  }
183
199
 
200
+ async simulateIntention(intention: TxIntention): Promise<SimulationResult> {
201
+ const txb = await buildIntentionTransaction(this.suiClient, intention, this.address);
202
+ if (!txb.blockData.gasConfig.price) {
203
+ const refGas = await this.suiClient.getReferenceGasPrice();
204
+ txb.setGasPrice(refGas);
205
+ }
206
+ const payload = await txb.build({ client: this.suiClient });
207
+ const dryRunResult = await this.suiClient.dryRunTransactionBlock({ transactionBlock: payload });
208
+
209
+ const success = dryRunResult.effects.status.status === 'success';
210
+ const errorMsg = dryRunResult.effects.status.error;
211
+ const gasPrice = BigInt(txb.blockData.gasConfig.price as string);
212
+ const { gasUsed } = dryRunResult.effects;
213
+
214
+ return {
215
+ success,
216
+ errorMsg,
217
+ gasPrice,
218
+ gasUsed,
219
+ dryRunResult,
220
+ };
221
+ }
222
+
184
223
  async executePendingTx(pending: PendingTx) {
185
224
  let gotSigs: Map<string, string>;
186
225
  let payload: string;
@@ -30,11 +30,12 @@ export class MessageHelper {
30
30
  }
31
31
 
32
32
  static proposeIntentionMessage(data: ProposeIntentionData) {
33
- const { intention, sn } = data;
33
+ const { msafeAddress, intention, sn } = data;
34
34
  const intentionData = IntentionHelper.ser(intention);
35
35
  const msg: ProposeIntentionMessage = {
36
36
  intentionData,
37
37
  sequenceNumber: sn,
38
+ msafeAddress,
38
39
  };
39
40
  return JSON.stringify(msg);
40
41
  }
@@ -49,8 +50,9 @@ export class MessageHelper {
49
50
  ) {
50
51
  throw new Error('Invalid intention data');
51
52
  }
52
- const { sequenceNumber, intentionData } = de;
53
+ const { msafeAddress, sequenceNumber, intentionData } = de;
53
54
  return {
55
+ msafeAddress,
54
56
  sn: sequenceNumber,
55
57
  intention: IntentionHelper.de(intentionData),
56
58
  };
@@ -81,11 +83,13 @@ export class MessageHelper {
81
83
  }
82
84
 
83
85
  export interface ProposeIntentionData {
86
+ msafeAddress: string;
84
87
  intention: TxIntention;
85
88
  sn: number;
86
89
  }
87
90
 
88
91
  export interface ProposeIntentionMessage {
92
+ msafeAddress: string;
89
93
  intentionData: string;
90
94
  sequenceNumber: number;
91
95
  }
@@ -53,6 +53,8 @@ export const DEV_DATABASE_CONFIG: DBConfig = {
53
53
  logging: false,
54
54
  };
55
55
 
56
+ export const MSAFE_APPLICATION = 'msafe';
57
+
56
58
  export const TESTNET_RPC_URL = 'https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD';
57
59
  export const MAINNET_RPC_URL = 'https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7';
58
60
 
@@ -1,3 +1,5 @@
1
+ import { GasCostSummary, DryRunTransactionBlockResponse } from '@mysten/sui.js/client';
2
+
1
3
  import { TxIntention } from '@/transactions/intention';
2
4
 
3
5
  export interface PendingTx {
@@ -10,9 +12,9 @@ export interface PendingTx {
10
12
  createdAt: Date;
11
13
  sequenceNumber: number;
12
14
  votes: PendingVote[];
13
- rejectDigest?: string;
14
- rejectPayload?: string;
15
- rejectVotes?: PendingVote[];
15
+ rejectDigest: string;
16
+ rejectPayload: string;
17
+ rejectVotes: PendingVote[];
16
18
  }
17
19
 
18
20
  export interface PendingVote {
@@ -62,3 +64,13 @@ export interface FutureIntention {
62
64
  statusRemark?: string;
63
65
  createdAt: Date;
64
66
  }
67
+
68
+ export interface SimulationResult {
69
+ success: boolean;
70
+ errorMsg?: string;
71
+ // gas price for the simulation
72
+ gasPrice: bigint;
73
+ // detailed gas cost summary
74
+ gasUsed: GasCostSummary;
75
+ dryRunResult: DryRunTransactionBlockResponse;
76
+ }