@msafe/sui3-sdk 0.0.15-pre-3e855d9.0 → 0.0.16

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,23 +1,32 @@
1
1
  import {
2
- HistoryTransaction,
2
+ GetHistoryTransactionsResponse,
3
+ GetPendingTransactionResponse,
4
+ GetTransactionIntentionsResponse,
3
5
  IAuthLoginReq,
4
6
  IAuthLoginResp,
7
+ IBuildTransactionRequest,
5
8
  ICreateMSafeReq,
9
+ IGetAddressBookResult,
10
+ IGetHistoryTransactionsRequest,
11
+ IGetIntentionsRequest,
6
12
  IGetMSafeQuery,
7
13
  IGetMSafesQuery,
14
+ IGetPendingTransactionRequest,
8
15
  IGetPublicKeyBatchQuery,
9
16
  IGetPublicKeyBatchResp,
17
+ IMSafeConfig,
10
18
  IMSafeInfoResp,
11
- IPagedResult,
12
19
  IPageOptions,
20
+ IPagedResult,
21
+ IProposeIntentionRequest,
22
+ ISkipIntentionRequest,
13
23
  IUpdateMSafeStatusReq,
14
24
  IUserInfoResp,
25
+ IVoteTransactionRequest,
15
26
  JWTToken,
16
27
  PublicKeySerde,
17
- UserMSafeStatus,
18
- IGetAddressBookResult,
19
28
  UpdateAddressBookEntry,
20
- IMSafeConfig,
29
+ UserMSafeStatus,
21
30
  } from '@msafe/sui3-utils';
22
31
  import { SerializedSignature } from '@mysten/sui.js/cryptography';
23
32
  import { PublicKey } from '@mysten/sui.js/src/cryptography';
@@ -25,7 +34,6 @@ import axios from 'axios';
25
34
 
26
35
  import { IBackend } from '@/backend/interface';
27
36
  import { TxIntention } from '@/transactions/intention';
28
- import { FutureIntention, PendingTx, ProposeIntention } from '@/types/msafe';
29
37
 
30
38
  export class BackendImpl implements IBackend {
31
39
  private _token: JWTToken;
@@ -137,8 +145,9 @@ export class BackendImpl implements IBackend {
137
145
  }
138
146
  }
139
147
 
140
- async getPendingTransactions(msafeAddress: string): Promise<PendingTx[]> {
141
- const res = await axios.get<PendingTx[]>(`${this.apiURL}/transaction/pending/${msafeAddress}`, {
148
+ async getPendingTransactions(input: IGetPendingTransactionRequest): Promise<GetPendingTransactionResponse> {
149
+ const res = await axios.get<GetPendingTransactionResponse>(`${this.apiURL}/transaction/pending`, {
150
+ params: input,
142
151
  headers: this.headers(),
143
152
  });
144
153
  if (res.status !== 200 && res.status !== 201) {
@@ -147,35 +156,20 @@ export class BackendImpl implements IBackend {
147
156
  return res.data;
148
157
  }
149
158
 
150
- async getHistoryTransactions(
151
- msafeAddress: string,
152
- paginationOption?: IPageOptions,
153
- ): Promise<IPagedResult<HistoryTransaction>> {
154
- const res = await axios.get<IPagedResult<HistoryTransaction>>(
155
- `${this.apiURL}/transaction/history?address=${msafeAddress}`,
156
- {
157
- params: {
158
- page: paginationOption?.page,
159
- limit: paginationOption?.limit,
160
- },
161
- headers: this.headers(),
162
- },
163
- );
159
+ async getHistoryTransactions(input: IGetHistoryTransactionsRequest): Promise<GetHistoryTransactionsResponse> {
160
+ const res = await axios.get<GetHistoryTransactionsResponse>(`${this.apiURL}/transaction/history`, {
161
+ params: input,
162
+ headers: this.headers(),
163
+ });
164
164
  if (res.status !== 200 && res.status !== 201) {
165
165
  throw new Error(`invalid getCurrentSequenceNumber return: ${res}`);
166
166
  }
167
167
  return res.data;
168
168
  }
169
169
 
170
- async getFutureIntentions(
171
- msafeAddress: string,
172
- paginationOption?: IPageOptions,
173
- ): Promise<IPagedResult<FutureIntention>> {
174
- const res = await axios.get<IPagedResult<FutureIntention>>(`${this.apiURL}/transaction/intention/${msafeAddress}`, {
175
- params: {
176
- page: paginationOption?.page,
177
- limit: paginationOption?.limit,
178
- },
170
+ async getFutureIntentions(input: IGetIntentionsRequest): Promise<GetTransactionIntentionsResponse> {
171
+ const res = await axios.get<GetTransactionIntentionsResponse>(`${this.apiURL}/transaction/intention`, {
172
+ params: input,
179
173
  headers: this.headers(),
180
174
  });
181
175
  if (res.status !== 200 && res.status !== 201) {
@@ -184,8 +178,11 @@ export class BackendImpl implements IBackend {
184
178
  return res.data;
185
179
  }
186
180
 
187
- async getCurrentSequenceNumber(msafeAddress: string): Promise<number> {
188
- const res = await axios.get<number>(`${this.apiURL}/transaction/sn/current/${msafeAddress}`, {
181
+ async getCurrentSequenceNumber(address: string): Promise<number> {
182
+ const res = await axios.get<number>(`${this.apiURL}/transaction/sn/current`, {
183
+ params: {
184
+ msafeAddress: address,
185
+ },
189
186
  headers: this.headers(),
190
187
  });
191
188
  if (res.status !== 200 && res.status !== 201) {
@@ -194,8 +191,11 @@ export class BackendImpl implements IBackend {
194
191
  return res.data;
195
192
  }
196
193
 
197
- async getNextSequenceNumber(msafeAddress: string): Promise<number> {
198
- const res = await axios.get<number>(`${this.apiURL}/transaction/sn/next/${msafeAddress}`, {
194
+ async getNextSequenceNumber(address: string): Promise<number> {
195
+ const res = await axios.get<number>(`${this.apiURL}/transaction/sn/next`, {
196
+ params: {
197
+ msafeAddress: address,
198
+ },
199
199
  headers: this.headers(),
200
200
  });
201
201
  if (res.status !== 200 && res.status !== 201) {
@@ -213,7 +213,7 @@ export class BackendImpl implements IBackend {
213
213
  }
214
214
  }
215
215
 
216
- async proposeIntention(input: ProposeIntention): Promise<void> {
216
+ async proposeIntention(input: IProposeIntentionRequest): Promise<void> {
217
217
  const res = await axios.post(`${this.apiURL}/transaction/intention`, input, { headers: this.headers() });
218
218
  if (res.status !== 200 && res.status !== 201) {
219
219
  throw new Error(`invalid proposeIntention return: ${res}`);
@@ -232,71 +232,33 @@ export class BackendImpl implements IBackend {
232
232
  return undefined;
233
233
  }
234
234
 
235
- async rejectCurrentTx(input: {
236
- userAddress: string;
237
- msafeAddress: string;
238
- digest: string;
239
- signature: SerializedSignature;
240
- }) {
241
- const res = await axios.post(
242
- `${this.apiURL}/transaction/pending/reject`,
243
- {
244
- address: input.msafeAddress,
245
- digest: input.digest,
246
- signature: input.signature,
247
- },
248
- {
249
- headers: this.headers(),
250
- },
251
- );
235
+ async rejectCurrentTx(input: IVoteTransactionRequest) {
236
+ const res = await axios.post(`${this.apiURL}/transaction/pending/reject`, input, {
237
+ headers: this.headers(),
238
+ });
252
239
  if (res.status !== 200 && res.status !== 201) {
253
240
  throw new Error(`invalid voteForTransaction return: ${res}`);
254
241
  }
255
242
  }
256
243
 
257
- async voteForTransaction(input: {
258
- txDigest: string;
259
- msafeAddress: string;
260
- userAddress: string;
261
- signature: SerializedSignature;
262
- }) {
263
- const res = await axios.post(
264
- `${this.apiURL}/transaction/pending/vote`,
265
- {
266
- address: input.msafeAddress,
267
- digest: input.txDigest,
268
- signature: input.signature,
269
- },
270
- {
271
- headers: this.headers(),
272
- },
273
- );
244
+ async voteForTransaction(input: IVoteTransactionRequest) {
245
+ const res = await axios.post(`${this.apiURL}/transaction/pending/vote`, input, {
246
+ headers: this.headers(),
247
+ });
274
248
  if (res.status !== 200 && res.status !== 201) {
275
249
  throw new Error(`invalid voteForTransaction return: ${res}`);
276
250
  }
277
251
  }
278
252
 
279
- async buildNextIntentionAndAddToPending(input: { msafeAddress: string }) {
280
- const res = await axios.post(
281
- `${this.apiURL}/transaction/pending/build`,
282
- {
283
- address: input.msafeAddress,
284
- },
285
- { headers: this.headers() },
286
- );
253
+ async buildNextIntentionAndAddToPending(input: IBuildTransactionRequest) {
254
+ const res = await axios.post(`${this.apiURL}/transaction/pending/build`, input, { headers: this.headers() });
287
255
  if (res.status !== 200 && res.status !== 201) {
288
256
  throw new Error(`invalid buildNextIntentionAndAddToPending return: ${res}`);
289
257
  }
290
258
  }
291
259
 
292
- async skipNextFailedIntention(input: { msafeAddress: string; userAddress: string }) {
293
- const res = await axios.post(
294
- `${this.apiURL}/transaction/pending/skip`,
295
- {
296
- msafeAddress: input.msafeAddress,
297
- },
298
- { headers: this.headers() },
299
- );
260
+ async skipNextFailedIntention(input: ISkipIntentionRequest) {
261
+ const res = await axios.post(`${this.apiURL}/transaction/pending/skip`, input, { headers: this.headers() });
300
262
  if (res.status !== 200 && res.status !== 201) {
301
263
  throw new Error(`invalid skipNextFailedIntention return: ${res}`);
302
264
  }
@@ -1,20 +1,28 @@
1
1
  import {
2
- HistoryTransaction,
2
+ GetHistoryTransactionsResponse,
3
+ GetPendingTransactionResponse,
4
+ GetTransactionIntentionsResponse,
3
5
  IAuthLoginReq,
6
+ IBuildTransactionRequest,
4
7
  ICreateMSafeReq,
5
- IPageOptions,
6
- IUserInfoResp,
7
- UserMSafeStatus,
8
8
  IGetAddressBookResult,
9
+ IGetHistoryTransactionsRequest,
10
+ IGetIntentionsRequest,
11
+ IGetPendingTransactionRequest,
12
+ IMSafeConfig,
13
+ IPageOptions,
9
14
  IPagedResult,
10
- UpdateAddressBookEntry,
15
+ IProposeIntentionRequest,
16
+ ISkipIntentionRequest,
17
+ IUserInfoResp,
18
+ IVoteTransactionRequest,
11
19
  JWTToken,
12
- IMSafeConfig,
20
+ UpdateAddressBookEntry,
21
+ UserMSafeStatus,
13
22
  } from '@msafe/sui3-utils';
14
23
  import { PublicKey, SerializedSignature } from '@mysten/sui.js/cryptography';
15
24
 
16
25
  import { TxIntention } from '@/transactions/intention';
17
- import { FutureIntention, PendingTx, ProposeIntention } from '@/types/msafe';
18
26
 
19
27
  export interface IBackend {
20
28
  authSign(input: IAuthLoginReq): Promise<JWTToken>;
@@ -31,17 +39,14 @@ export interface IBackend {
31
39
  }): Promise<IPagedResult<IMSafeConfig>>;
32
40
  updateMSafeStatus(input: { msafeAddress: string; status: UserMSafeStatus }): Promise<void>;
33
41
 
34
- getPendingTransactions(msafeAddress: string): Promise<PendingTx[]>;
35
- getHistoryTransactions(
36
- msafeAddress: string,
37
- paginationOption?: IPageOptions,
38
- ): Promise<IPagedResult<HistoryTransaction>>;
39
- getFutureIntentions(msafeAddress: string, paginationOption?: IPageOptions): Promise<IPagedResult<FutureIntention>>;
40
- getCurrentSequenceNumber(msafeAddress: string): Promise<number>;
41
- getNextSequenceNumber(msafeAddress: string): Promise<number>;
42
+ getPendingTransactions(input: IGetPendingTransactionRequest): Promise<GetPendingTransactionResponse>;
43
+ getHistoryTransactions(input: IGetHistoryTransactionsRequest): Promise<GetHistoryTransactionsResponse>;
44
+ getFutureIntentions(input: IGetIntentionsRequest): Promise<GetTransactionIntentionsResponse>;
45
+ getCurrentSequenceNumber(address: string): Promise<number>;
46
+ getNextSequenceNumber(address: string): Promise<number>;
42
47
 
43
48
  createMSafeAccount(input: ICreateMSafeReq): Promise<void>;
44
- proposeIntention(input: ProposeIntention): Promise<void>;
49
+ proposeIntention(input: IProposeIntentionRequest): Promise<void>;
45
50
  proposePendingTransaction(input: {
46
51
  intention: TxIntention;
47
52
  userAddress: string;
@@ -49,20 +54,10 @@ export interface IBackend {
49
54
  digest: string;
50
55
  signature: SerializedSignature;
51
56
  }): Promise<void>;
52
- rejectCurrentTx(input: {
53
- userAddress: string;
54
- msafeAddress: string;
55
- digest: string;
56
- signature: SerializedSignature;
57
- }): Promise<void>;
58
- voteForTransaction(input: {
59
- txDigest: string;
60
- msafeAddress: string;
61
- userAddress: string;
62
- signature: SerializedSignature;
63
- }): Promise<void>;
64
- buildNextIntentionAndAddToPending(input: { msafeAddress: string }): Promise<void>;
65
- skipNextFailedIntention(input: { msafeAddress: string; userAddress: string }): Promise<void>;
57
+ rejectCurrentTx(input: IVoteTransactionRequest): Promise<void>;
58
+ voteForTransaction(input: IVoteTransactionRequest): Promise<void>;
59
+ buildNextIntentionAndAddToPending(input: IBuildTransactionRequest): Promise<void>;
60
+ skipNextFailedIntention(input: ISkipIntentionRequest): Promise<void>;
66
61
  processExecutedTransaction(digest: string): Promise<void>;
67
62
 
68
63
  getAddressBookEntries(pagination?: IPageOptions): Promise<IGetAddressBookResult>;
@@ -1,19 +1,24 @@
1
1
  import {
2
- buildIntentionTransaction,
2
+ CoinTransferIntention,
3
3
  IMSafeConfig,
4
- IPageOptions,
4
+ IProposeIntentionRequest,
5
5
  MultiSigAccount,
6
+ ObjectTransferIntention,
6
7
  SigningMessageHelper,
8
+ TransactionDefaultApplication,
9
+ TransactionSubTypes,
10
+ TransactionType,
7
11
  } from '@msafe/sui3-utils';
8
12
  import { SuiObjectData } from '@mysten/sui.js/client';
9
13
  import { SerializedSignature } from '@mysten/sui.js/cryptography';
10
14
  import { SuiObjectResponse } from '@mysten/sui.js/src/client';
15
+ import { TransactionBlock } from '@mysten/sui.js/transactions';
11
16
  import { normalizeStructTag } from '@mysten/sui.js/utils';
12
17
 
13
18
  import { MSafeGlobals } from '@/globals/MSafeGlobals';
14
19
  import { IntentionHelper, TxIntention } from '@/transactions/intention';
15
20
  import { OwnedCoin } from '@/types/assets';
16
- import { PendingTx, SimulationResult } from '@/types/msafe';
21
+ import { Pagination, PendingTx, SimulationResult } from '@/types/msafe';
17
22
  import { CoinHelper } from '@/utils';
18
23
  import { HexToUint8Array } from '@/utils/buffer';
19
24
  import { BatchObjectOptions, getAllOwnedObjects } from '@/utils/iter/object';
@@ -70,32 +75,40 @@ export class MSafeAccount {
70
75
  }
71
76
 
72
77
  async pendingTransaction(): Promise<PendingTx | undefined> {
73
- const pendings = await this.backend.getPendingTransactions(this.address);
74
- if (pendings.length > 2) {
75
- throw new Error(`invalid backend getPendingTransactions resp, length should not > 2: ${pendings}`);
76
- }
77
- if (pendings.length === 0) {
78
+ const res = await this.backend.getPendingTransactions({ msafeAddress: this.address });
79
+ if (!res.pending) {
78
80
  return undefined;
79
81
  }
80
82
 
81
- const pendingTx = pendings.find((tx) => !tx.isRejectTx);
82
- const rejectPending = pendings.find((tx) => tx.isRejectTx);
83
+ const pendingTx = res.pending;
84
+ const rejectPending = res.reject;
83
85
 
84
86
  return {
85
- ...pendingTx!,
87
+ txType: TransactionType.Assets,
88
+ txSubType: TransactionSubTypes.assets.coin.send,
89
+ createdAt: pendingTx.createdAt as Date,
90
+ creator: pendingTx.creator,
91
+ digest: pendingTx.digest,
92
+ intention: pendingTx.intention,
93
+ sequenceNumber: pendingTx.sequenceNumber,
94
+ payload: pendingTx.payload,
95
+ votes: pendingTx.votes,
96
+ msafeAddress: pendingTx.msafeAddress,
86
97
  rejectDigest: rejectPending?.digest ?? '',
87
98
  rejectPayload: rejectPending?.payload ?? '',
88
99
  rejectVotes: rejectPending?.votes ?? [],
89
100
  };
90
101
  }
91
102
 
92
- async historyTransaction(paginationOption?: IPageOptions) {
93
- return this.backend.getHistoryTransactions(this.address, paginationOption);
103
+ async historyTransaction(pagination?: Pagination) {
104
+ return this.backend.getHistoryTransactions({
105
+ msafeAddress: this.address,
106
+ ...pagination,
107
+ });
94
108
  }
95
109
 
96
- async futureIntentions(paginationOption?: IPageOptions) {
97
- const paginatedIntentions = await this.backend.getFutureIntentions(this.address, paginationOption);
98
- return paginatedIntentions.data;
110
+ async futureIntentions(pagination?: Pagination) {
111
+ return this.backend.getFutureIntentions({ msafeAddress: this.address, ...pagination });
99
112
  }
100
113
 
101
114
  async currentSequenceNumber() {
@@ -106,13 +119,7 @@ export class MSafeAccount {
106
119
  return this.backend.getNextSequenceNumber(this.address);
107
120
  }
108
121
 
109
- async proposeIntention(input: {
110
- application: string;
111
- txType: string;
112
- txSubType: string;
113
- intention: TxIntention;
114
- sequenceNumber: number;
115
- }) {
122
+ async proposeIntention(input: Omit<IProposeIntentionRequest, 'signature' | 'msafeAddress'>) {
116
123
  const message = SigningMessageHelper.proposeIntentionMessage({
117
124
  msafeAddress: this.address,
118
125
  intention: input.intention,
@@ -122,22 +129,41 @@ export class MSafeAccount {
122
129
  messageStr: message,
123
130
  });
124
131
 
125
- // TODO get application from common utils
126
132
  await this.backend.proposeIntention({
127
133
  ...input,
128
134
  msafeAddress: this.address,
129
- userAddress: await this.userAddress(),
130
135
  signature: signature.signature,
131
136
  });
132
137
  }
133
138
 
139
+ async proposeCoinTransferIntention(intention: CoinTransferIntention) {
140
+ const sn = await this.nextSequenceNumber();
141
+ return this.proposeIntention({
142
+ application: TransactionDefaultApplication,
143
+ txType: TransactionType.Assets,
144
+ txSubType: TransactionSubTypes.assets.coin.send,
145
+ sequenceNumber: sn,
146
+ intention,
147
+ });
148
+ }
149
+
150
+ async proposeObjectTransferIntention(intention: ObjectTransferIntention) {
151
+ const sn = await this.nextSequenceNumber();
152
+ return this.proposeIntention({
153
+ application: TransactionDefaultApplication,
154
+ txType: TransactionType.Assets,
155
+ txSubType: TransactionSubTypes.assets.object.send,
156
+ sequenceNumber: sn,
157
+ intention,
158
+ });
159
+ }
160
+
134
161
  async voteForTransaction(digest: string, payload: string) {
135
162
  const payloadBytes = HexToUint8Array(payload);
136
163
  const signature = await this.wallet.signTransactionBlock({ transactionBlock: payloadBytes });
137
164
  return this.backend.voteForTransaction({
138
165
  msafeAddress: this.address,
139
- userAddress: await this.userAddress(),
140
- txDigest: digest,
166
+ digest,
141
167
  signature: signature.signature,
142
168
  });
143
169
  }
@@ -162,21 +188,13 @@ export class MSafeAccount {
162
188
  });
163
189
  }
164
190
 
165
- async rejectCurrentTx(pending?: PendingTx) {
166
- let payloadToReject: string;
167
- if (pending) {
168
- if (pending.isRejectTx) {
169
- throw new Error('Pending not reject transaction');
170
- }
171
- payloadToReject = pending.payload;
172
- } else {
173
- const pendingTx = await this.pendingTransaction();
174
- if (!pendingTx || pendingTx.rejectDigest !== '') {
175
- throw new Error('Already rejected');
176
- }
177
-
178
- payloadToReject = pendingTx.payload;
191
+ async rejectCurrentTx() {
192
+ const pendingTx = await this.pendingTransaction();
193
+ if (!pendingTx || pendingTx.rejectDigest !== '') {
194
+ throw new Error('Already rejected');
179
195
  }
196
+
197
+ const payloadToReject = pendingTx.payload;
180
198
  const rejectTxb = await IntentionHelper.buildRejectTransaction({
181
199
  msafeAddress: this.address,
182
200
  payloadToReject,
@@ -186,7 +204,6 @@ export class MSafeAccount {
186
204
  const signature = await this.wallet.signTransactionBlock({ transactionBlock: payload });
187
205
  return this.backend.rejectCurrentTx({
188
206
  msafeAddress: this.address,
189
- userAddress: await this.userAddress(),
190
207
  digest,
191
208
  signature: signature.signature,
192
209
  });
@@ -197,11 +214,13 @@ export class MSafeAccount {
197
214
  }
198
215
 
199
216
  async skipNextFailedIntention() {
200
- return this.backend.skipNextFailedIntention({ msafeAddress: this.address, userAddress: await this.userAddress() });
217
+ return this.backend.skipNextFailedIntention({ msafeAddress: this.address });
201
218
  }
202
219
 
203
- async simulateIntention(intention: TxIntention): Promise<SimulationResult> {
204
- const txb = await buildIntentionTransaction(this.suiClient, intention, this.address);
220
+ async simulateIntention(intention: any): Promise<SimulationResult> {
221
+ // Todo, move to API
222
+ const txb = new TransactionBlock(); // await buildIntentionTransaction(this.suiClient, intention, this.address);
223
+ txb.setSender(this.address);
205
224
  if (!txb.blockData.gasConfig.price) {
206
225
  const refGas = await this.suiClient.getReferenceGasPrice();
207
226
  txb.setGasPrice(refGas);
@@ -1,13 +1,15 @@
1
- import { GasCostSummary, DryRunTransactionBlockResponse } from '@mysten/sui.js/client';
1
+ import { TransactionType } from '@msafe/sui3-utils';
2
+ import { DryRunTransactionBlockResponse, GasCostSummary } from '@mysten/sui.js/client';
2
3
  import { SerializedSignature } from '@mysten/sui.js/cryptography';
3
4
 
4
5
  import { TxIntention } from '@/transactions/intention';
5
6
 
6
7
  export interface PendingTx {
8
+ txType: TransactionType;
9
+ txSubType: string;
7
10
  digest: string;
8
11
  payload: string;
9
12
  msafeAddress: string;
10
- isRejectTx: boolean;
11
13
  intention: TxIntention;
12
14
  creator: string;
13
15
  createdAt: Date;
@@ -86,3 +88,8 @@ export interface SimulationResult {
86
88
  gasUsed: GasCostSummary;
87
89
  dryRunResult: DryRunTransactionBlockResponse;
88
90
  }
91
+
92
+ export interface Pagination {
93
+ page?: string;
94
+ limit?: string;
95
+ }