@msafe/sui3-sdk 0.0.5 → 0.0.6-pre-fdcc3ff.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.
- package/dist/index.cjs +258 -969
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -89
- package/dist/index.d.ts +24 -89
- package/dist/index.js +251 -958
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/backend/BackendImpl.ts +196 -0
- package/src/backend/PseudoBackend.ts +25 -14
- package/src/backend/interface.ts +10 -10
- package/src/backend/types.ts +0 -21
- package/src/core/CreateHelper.ts +22 -12
- package/src/core/MSafeAccount.ts +9 -5
- package/src/core/MSafeClient.ts +2 -6
- package/src/globals/MSafeGlobals.ts +2 -1
- package/src/globals/const.ts +8 -1
- package/src/types/msafe.ts +0 -20
- package/src/utils/index.ts +0 -1
- package/src/utils/multi-sig.ts +0 -113
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthLoginRequest,
|
|
3
|
+
AuthLoginResponse,
|
|
4
|
+
CreateMSafeAccountInfoRequest,
|
|
5
|
+
GetMSafeAccountInfoResponse,
|
|
6
|
+
MSafeAccountInfo,
|
|
7
|
+
OwnerWithWeightPK,
|
|
8
|
+
PublicKeyWithScheme,
|
|
9
|
+
UserWithOwnedMSafe,
|
|
10
|
+
UserWithOwnedMSafeResponse,
|
|
11
|
+
} from '@msafe/sui3-utils';
|
|
12
|
+
import { SerializedSignature } from '@mysten/sui.js/cryptography';
|
|
13
|
+
import { PublicKey } from '@mysten/sui.js/src/cryptography';
|
|
14
|
+
import axios from 'axios';
|
|
15
|
+
|
|
16
|
+
import { IBackend } from '@/backend/interface';
|
|
17
|
+
import { JWTToken } from '@/backend/types';
|
|
18
|
+
import { TxIntention } from '@/transactions/intention';
|
|
19
|
+
import { FutureIntention, HistorySendTx, PendingTx } from '@/types/msafe';
|
|
20
|
+
import { PublicKeySerde } from '@/utils/crypto';
|
|
21
|
+
|
|
22
|
+
export class BackendImpl implements IBackend {
|
|
23
|
+
private _token: JWTToken;
|
|
24
|
+
|
|
25
|
+
constructor(private readonly apiURL: string) {}
|
|
26
|
+
|
|
27
|
+
async authSign(input: AuthLoginRequest): Promise<JWTToken> {
|
|
28
|
+
const res = await axios.post<AuthLoginResponse>(`${this.apiURL}/auth/login`, input);
|
|
29
|
+
// TODO unify response struct
|
|
30
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
31
|
+
throw new Error(`invalid authSign return: ${res}`);
|
|
32
|
+
}
|
|
33
|
+
this._token = res.data.accessToken;
|
|
34
|
+
return this._token;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setJWTToken(token: JWTToken) {
|
|
38
|
+
this._token = token;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async getPublicKey(address: string): Promise<PublicKey | undefined> {
|
|
42
|
+
return (await this.getPublicKeyBatch([address]))[0];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getPublicKeyBatch(addresses: string[]): Promise<(PublicKey | undefined)[]> {
|
|
46
|
+
const res = await axios.post<(PublicKeyWithScheme | undefined)[]>(
|
|
47
|
+
`${this.apiURL}/account/getPublicKeyBatch`,
|
|
48
|
+
addresses,
|
|
49
|
+
{
|
|
50
|
+
headers: this.headers(),
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
// TODO unify response struct
|
|
54
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
55
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return res.data?.map((publicKeyWithSchema) =>
|
|
59
|
+
publicKeyWithSchema ? PublicKeySerde.de({ ...publicKeyWithSchema }) : undefined,
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async getMSafeAccountInfo(msafeAddress: string): Promise<MSafeAccountInfo> {
|
|
64
|
+
const res = await axios.get<GetMSafeAccountInfoResponse>(
|
|
65
|
+
`${this.apiURL}/account/getMSafeAccountInfo/${msafeAddress}`,
|
|
66
|
+
{
|
|
67
|
+
headers: this.headers(),
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// TODO unify response struct
|
|
72
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
73
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const msafeResp = res.data;
|
|
77
|
+
return {
|
|
78
|
+
address: msafeResp.address,
|
|
79
|
+
ownersWithWeightPK: msafeResp.ownersWithWeightPKEncoded.map(
|
|
80
|
+
(owner): OwnerWithWeightPK => ({
|
|
81
|
+
publicKey: PublicKeySerde.de({ publicKey: owner.publicKeyEncoded, scheme: owner.schema }),
|
|
82
|
+
address: owner.address,
|
|
83
|
+
weight: owner.weight,
|
|
84
|
+
}),
|
|
85
|
+
),
|
|
86
|
+
threshold: msafeResp.threshold,
|
|
87
|
+
name: msafeResp.name,
|
|
88
|
+
description: msafeResp.description,
|
|
89
|
+
creationNonce: msafeResp.creationNonce,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async getUserInfo(userAddress: string): Promise<UserWithOwnedMSafe> {
|
|
94
|
+
const res = await axios.get<UserWithOwnedMSafeResponse>(`${this.apiURL}/account/user/${userAddress}`, {
|
|
95
|
+
headers: this.headers(),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// TODO unify response struct
|
|
99
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
100
|
+
throw new Error(`invalid getPublicKeyBatch return: ${res}`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
address: res.data.address,
|
|
105
|
+
publicKey: res.data.publicKey,
|
|
106
|
+
schema: res.data.schema,
|
|
107
|
+
creationNonce: res.data.creationNonce,
|
|
108
|
+
ownedMSafe: res.data.ownedMSafe.map(
|
|
109
|
+
(msafe): MSafeAccountInfo => ({
|
|
110
|
+
address: msafe.address,
|
|
111
|
+
ownersWithWeightPK: msafe.ownersWithWeightPKEncoded.map(
|
|
112
|
+
(owner): OwnerWithWeightPK => ({
|
|
113
|
+
publicKey: PublicKeySerde.de({ publicKey: owner.publicKeyEncoded, scheme: owner.schema }),
|
|
114
|
+
address: owner.address,
|
|
115
|
+
weight: owner.weight,
|
|
116
|
+
}),
|
|
117
|
+
),
|
|
118
|
+
threshold: msafe.threshold,
|
|
119
|
+
name: msafe.name,
|
|
120
|
+
description: msafe.description,
|
|
121
|
+
creationNonce: msafe.creationNonce,
|
|
122
|
+
}),
|
|
123
|
+
),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async getPendingTransactions(msafeAddress: string): Promise<PendingTx[]> {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async getHistoryTransactions(msafeAddress: string): Promise<HistorySendTx[]> {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async getFutureIntentions(msafeAddress: string): Promise<FutureIntention[]> {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async getCurrentSequenceNumber(msafeAddress: string): Promise<number> {
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async getNextSequenceNumber(msafeAddress: string): Promise<number> {
|
|
144
|
+
return 0;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async createMSafeAccount(input: CreateMSafeAccountInfoRequest): Promise<void> {
|
|
148
|
+
const res = await axios.post(`${this.apiURL}/account`, input, {
|
|
149
|
+
headers: this.headers(),
|
|
150
|
+
});
|
|
151
|
+
if (res.status !== 200 && res.status !== 201) {
|
|
152
|
+
throw new Error(`invalid createMSafeAccount return: ${res}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async proposeIntention(input: {
|
|
157
|
+
intention: TxIntention;
|
|
158
|
+
sequenceNumber: number;
|
|
159
|
+
userAddress: string;
|
|
160
|
+
msafeAddress: string;
|
|
161
|
+
signature: SerializedSignature;
|
|
162
|
+
}): Promise<void> {
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async proposePendingTransaction(input: {
|
|
166
|
+
intention: TxIntention;
|
|
167
|
+
userAddress: string;
|
|
168
|
+
msafeAddress: string;
|
|
169
|
+
digest: string;
|
|
170
|
+
signature: SerializedSignature;
|
|
171
|
+
}): Promise<void> {}
|
|
172
|
+
|
|
173
|
+
async rejectCurrentTx(input: {
|
|
174
|
+
userAddress: string;
|
|
175
|
+
msafeAddress: string;
|
|
176
|
+
digest: string;
|
|
177
|
+
signature: SerializedSignature;
|
|
178
|
+
}) {}
|
|
179
|
+
|
|
180
|
+
async voteForTransaction(input: {
|
|
181
|
+
txDigest: string;
|
|
182
|
+
msafeAddress: string;
|
|
183
|
+
userAddress: string;
|
|
184
|
+
signature: SerializedSignature;
|
|
185
|
+
}) {}
|
|
186
|
+
|
|
187
|
+
async buildNextIntentionAndAddToPending(input: { msafeAddress: string }) {}
|
|
188
|
+
|
|
189
|
+
async skipNextFailedIntention(input: { msafeAddress: string; userAddress: string }) {}
|
|
190
|
+
|
|
191
|
+
async processExecutedTransaction(digest: string) {}
|
|
192
|
+
|
|
193
|
+
private headers() {
|
|
194
|
+
return { Authorization: `Bearer ${this._token}` };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -8,6 +8,14 @@ import {
|
|
|
8
8
|
UserVote,
|
|
9
9
|
PendingTransaction,
|
|
10
10
|
} from '@msafe/sui3-model/core';
|
|
11
|
+
import {
|
|
12
|
+
CreateMSafeAccountInfoRequest,
|
|
13
|
+
deserializePublicKey,
|
|
14
|
+
MSafeAccountInfo,
|
|
15
|
+
MultisigAccountManager,
|
|
16
|
+
OwnerWithWeightPK,
|
|
17
|
+
UserWithOwnedMSafe,
|
|
18
|
+
} from '@msafe/sui3-utils';
|
|
11
19
|
import { SuiClient } from '@mysten/sui.js/client';
|
|
12
20
|
import { PublicKey, SerializedSignature } from '@mysten/sui.js/cryptography';
|
|
13
21
|
import { SignatureScheme } from '@mysten/sui.js/src/cryptography/signature-scheme';
|
|
@@ -15,15 +23,14 @@ import { MoreThanOrEqual } from 'typeorm';
|
|
|
15
23
|
|
|
16
24
|
import { CoreDB } from '@/backend/CoreDatabase';
|
|
17
25
|
import { IBackend } from '@/backend/interface';
|
|
18
|
-
import {
|
|
26
|
+
import { JWTToken } from '@/backend/types';
|
|
19
27
|
import { MessageHelper } from '@/core/MessageHelper';
|
|
20
28
|
import { DBConfig } from '@/globals/const';
|
|
21
29
|
import { IntentionHelper, TxIntention } from '@/transactions/intention';
|
|
22
|
-
import { FutureIntention, HistorySendTx,
|
|
30
|
+
import { FutureIntention, HistorySendTx, PendingTx } from '@/types/msafe';
|
|
23
31
|
import { Uint8ArrayToHex, HexToUint8Array } from '@/utils/buffer';
|
|
24
32
|
import { PublicKeySerde, SignatureVerifier } from '@/utils/crypto';
|
|
25
33
|
import { Formatter } from '@/utils/format';
|
|
26
|
-
import { RawMultiSig } from '@/utils/multi-sig';
|
|
27
34
|
|
|
28
35
|
/**
|
|
29
36
|
* Represents a PseudoBackend class that implements the IBackend interface.
|
|
@@ -46,11 +53,6 @@ export class PseudoBackend implements IBackend {
|
|
|
46
53
|
return new PseudoBackend(db, suiClient);
|
|
47
54
|
}
|
|
48
55
|
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars,unused-imports/no-unused-vars
|
|
50
|
-
async isJWTTokenValid(_jwt: JWTToken): Promise<boolean> {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
56
|
async authSign(input: {
|
|
55
57
|
address: string;
|
|
56
58
|
message: string;
|
|
@@ -128,12 +130,21 @@ export class PseudoBackend implements IBackend {
|
|
|
128
130
|
return res;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
async createMSafeAccount(input:
|
|
132
|
-
const
|
|
133
|
-
|
|
133
|
+
async createMSafeAccount(input: CreateMSafeAccountInfoRequest) {
|
|
134
|
+
const ownersWithWeightPK: OwnerWithWeightPK[] = input.ownersWithWeightPKEncoded.map((owner) => ({
|
|
135
|
+
address: owner.address,
|
|
136
|
+
weight: owner.weight,
|
|
137
|
+
publicKey: deserializePublicKey(owner.publicKeyEncoded, owner.schema),
|
|
138
|
+
}));
|
|
139
|
+
const multisigManager = new MultisigAccountManager({
|
|
140
|
+
threshold: input.threshold,
|
|
141
|
+
creationNonce: input.creationNonce,
|
|
142
|
+
ownersWithWeight: ownersWithWeightPK,
|
|
143
|
+
});
|
|
144
|
+
const msafeAddr = multisigManager.address;
|
|
134
145
|
|
|
135
146
|
const signingMsg = MessageHelper.createMSafeMessage(msafeAddr);
|
|
136
|
-
const targetAddr = input.
|
|
147
|
+
const targetAddr = input.ownersWithWeightPKEncoded[0].address;
|
|
137
148
|
const verifyResult = await SignatureVerifier.verifyPersonalSignature({
|
|
138
149
|
messageStr: signingMsg,
|
|
139
150
|
signature: input.signature,
|
|
@@ -151,7 +162,7 @@ export class PseudoBackend implements IBackend {
|
|
|
151
162
|
if (input.description && input.description.length > 512) {
|
|
152
163
|
throw new Error('Description too long');
|
|
153
164
|
}
|
|
154
|
-
const creatorAddress = input.
|
|
165
|
+
const creatorAddress = input.ownersWithWeightPKEncoded[0].address;
|
|
155
166
|
const creator = await this.getUser(creatorAddress);
|
|
156
167
|
if (creator === null) {
|
|
157
168
|
throw new Error('Creator not found');
|
|
@@ -165,7 +176,7 @@ export class PseudoBackend implements IBackend {
|
|
|
165
176
|
if (msafeExistCheck !== null) {
|
|
166
177
|
throw new Error('MSafe already exist in database');
|
|
167
178
|
}
|
|
168
|
-
input.
|
|
179
|
+
input.ownersWithWeightPKEncoded.forEach((ownerInfo) => {
|
|
169
180
|
if (!Formatter.isSuiAddressEqual(ownerInfo.address, ownerInfo.publicKey.toSuiAddress())) {
|
|
170
181
|
throw new Error('Sui address public key not match');
|
|
171
182
|
}
|
package/src/backend/interface.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AuthLoginRequest,
|
|
3
|
+
CreateMSafeAccountInfoRequest,
|
|
4
|
+
MSafeAccountInfo,
|
|
5
|
+
UserWithOwnedMSafe,
|
|
6
|
+
} from '@msafe/sui3-utils';
|
|
1
7
|
import { PublicKey, SerializedSignature } from '@mysten/sui.js/cryptography';
|
|
2
8
|
|
|
3
|
-
import {
|
|
9
|
+
import { JWTToken } from '@/backend/types';
|
|
4
10
|
import { TxIntention } from '@/transactions/intention';
|
|
5
|
-
import { FutureIntention, HistorySendTx,
|
|
11
|
+
import { FutureIntention, HistorySendTx, PendingTx } from '@/types/msafe';
|
|
6
12
|
|
|
7
13
|
export interface IBackend {
|
|
8
|
-
|
|
9
|
-
authSign(input: {
|
|
10
|
-
address: string;
|
|
11
|
-
message: string;
|
|
12
|
-
signature: SerializedSignature;
|
|
13
|
-
walletType: string;
|
|
14
|
-
}): Promise<JWTToken>;
|
|
14
|
+
authSign(input: AuthLoginRequest): Promise<JWTToken>;
|
|
15
15
|
setJWTToken(token: JWTToken): void;
|
|
16
16
|
|
|
17
17
|
getPublicKey(address: string): Promise<PublicKey | undefined>;
|
|
@@ -24,7 +24,7 @@ export interface IBackend {
|
|
|
24
24
|
getCurrentSequenceNumber(msafeAddress: string): Promise<number>;
|
|
25
25
|
getNextSequenceNumber(msafeAddress: string): Promise<number>;
|
|
26
26
|
|
|
27
|
-
createMSafeAccount(input:
|
|
27
|
+
createMSafeAccount(input: CreateMSafeAccountInfoRequest): Promise<void>;
|
|
28
28
|
proposeIntention(input: {
|
|
29
29
|
intention: TxIntention;
|
|
30
30
|
sequenceNumber: number;
|
package/src/backend/types.ts
CHANGED
|
@@ -1,22 +1 @@
|
|
|
1
|
-
import { SerializedSignature } from '@mysten/sui.js/cryptography';
|
|
2
|
-
|
|
3
|
-
import { MSafeAccountInfo, OwnerWithWeightPK } from '@/types/msafe';
|
|
4
|
-
|
|
5
1
|
export type JWTToken = string;
|
|
6
|
-
|
|
7
|
-
export interface CreateMSafeParams {
|
|
8
|
-
ownerWithWeight: OwnerWithWeightPK[];
|
|
9
|
-
threshold: number;
|
|
10
|
-
name: string;
|
|
11
|
-
description?: string;
|
|
12
|
-
creationNonce: number;
|
|
13
|
-
signature: SerializedSignature;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface UserWithOwnedMSafe {
|
|
17
|
-
address: string;
|
|
18
|
-
publicKey: string;
|
|
19
|
-
schema: string;
|
|
20
|
-
creationNonce: number;
|
|
21
|
-
ownedMSafe: MSafeAccountInfo[];
|
|
22
|
-
}
|
package/src/core/CreateHelper.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAccountCreationMessage,
|
|
3
|
+
MultisigAccountManager,
|
|
4
|
+
MultiSigConfig,
|
|
5
|
+
OwnerWithWeightPKEncoded,
|
|
6
|
+
validateCreateAccountRequest,
|
|
7
|
+
} from '@msafe/sui3-utils';
|
|
1
8
|
import { PublicKey, SerializedSignature } from '@mysten/sui.js/cryptography';
|
|
2
9
|
|
|
3
|
-
import { MessageHelper } from '@/core/MessageHelper';
|
|
4
10
|
import { PublicKeyHelper } from '@/core/PublicKeyHelper';
|
|
5
11
|
import { MSafeGlobals } from '@/globals/MSafeGlobals';
|
|
6
12
|
import { CreateMSafeAccountInfo, CreatePermissionInfo } from '@/types/creation';
|
|
7
|
-
import {
|
|
13
|
+
import { PublicKeySerde } from '@/utils/crypto';
|
|
8
14
|
|
|
9
15
|
export class CreateHelper {
|
|
10
16
|
constructor(
|
|
@@ -18,14 +24,14 @@ export class CreateHelper {
|
|
|
18
24
|
|
|
19
25
|
async calculateMSafeAddress(info: CreatePermissionInfo) {
|
|
20
26
|
const msConfig = await this.reduceCreationInfoToRawConfig(info);
|
|
21
|
-
const ms = new
|
|
22
|
-
return ms.
|
|
27
|
+
const ms = new MultisigAccountManager(msConfig);
|
|
28
|
+
return ms.address;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
// Validate the create info and return the msafe address.
|
|
26
32
|
async validateCreateInfo(createInfo: CreateMSafeAccountInfo) {
|
|
27
33
|
const rawConfig = await this.reduceCreationInfoToRawConfig(createInfo);
|
|
28
|
-
|
|
34
|
+
validateCreateAccountRequest(rawConfig);
|
|
29
35
|
|
|
30
36
|
// Calculate the sui address will check the multi-sig
|
|
31
37
|
return this.calculateMSafeAddress(createInfo);
|
|
@@ -34,7 +40,7 @@ export class CreateHelper {
|
|
|
34
40
|
async submitMSafeCreation(creationInfo: CreateMSafeAccountInfo) {
|
|
35
41
|
const msafeAddress = await this.validateCreateInfo(creationInfo);
|
|
36
42
|
|
|
37
|
-
const signingMessage =
|
|
43
|
+
const signingMessage = createAccountCreationMessage(msafeAddress);
|
|
38
44
|
const signature = await this.globals.wallet.signPersonalMessage({ messageStr: signingMessage });
|
|
39
45
|
|
|
40
46
|
await this.submitToBackend(creationInfo, signature.signature);
|
|
@@ -50,7 +56,7 @@ export class CreateHelper {
|
|
|
50
56
|
});
|
|
51
57
|
return {
|
|
52
58
|
threshold: info.threshold,
|
|
53
|
-
|
|
59
|
+
ownersWithWeight: info.ownerWithWeight.map((owner, i) => ({
|
|
54
60
|
publicKey: publicKeys[i] as PublicKey,
|
|
55
61
|
weight: owner.weight,
|
|
56
62
|
})),
|
|
@@ -61,11 +67,15 @@ export class CreateHelper {
|
|
|
61
67
|
private async submitToBackend(createInfo: CreateMSafeAccountInfo, signature: SerializedSignature) {
|
|
62
68
|
const pks = await this.pkHelper.getPublicKeyBatch(createInfo.ownerWithWeight.map((owner) => owner.address));
|
|
63
69
|
await this.globals.backend.createMSafeAccount({
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
ownersWithWeightPKEncoded: createInfo.ownerWithWeight.map((owner, i): OwnerWithWeightPKEncoded => {
|
|
71
|
+
const publicKeySer = PublicKeySerde.ser(pks[i] as PublicKey);
|
|
72
|
+
return {
|
|
73
|
+
address: owner.address,
|
|
74
|
+
weight: owner.weight,
|
|
75
|
+
publicKeyEncoded: publicKeySer.publicKey,
|
|
76
|
+
schema: publicKeySer.scheme,
|
|
77
|
+
};
|
|
78
|
+
}),
|
|
69
79
|
threshold: createInfo.threshold,
|
|
70
80
|
name: createInfo.name, // name validation is deferred to backend
|
|
71
81
|
description: createInfo.description, // description validation is deferred to backend
|
package/src/core/MSafeAccount.ts
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
import { MSafeAccountInfo, MultisigAccountManager } from "@msafe/sui3-utils";
|
|
1
2
|
import { SerializedSignature } from '@mysten/sui.js/cryptography';
|
|
2
3
|
|
|
3
4
|
import { MessageHelper } from '@/core/MessageHelper';
|
|
4
5
|
import { MSafeGlobals } from '@/globals/MSafeGlobals';
|
|
5
6
|
import { IntentionHelper, TxIntention } from '@/transactions/intention';
|
|
6
|
-
import {
|
|
7
|
+
import { PendingTx } from '@/types/msafe';
|
|
7
8
|
import { HexToUint8Array } from '@/utils/buffer';
|
|
8
|
-
import { RawMultiSig } from '@/utils/multi-sig';
|
|
9
9
|
|
|
10
10
|
export class MSafeAccount {
|
|
11
|
-
public
|
|
11
|
+
public multisigManager: MultisigAccountManager;
|
|
12
12
|
|
|
13
13
|
constructor(
|
|
14
14
|
public readonly globals: MSafeGlobals,
|
|
15
15
|
public readonly info: MSafeAccountInfo,
|
|
16
16
|
) {
|
|
17
|
-
this.
|
|
17
|
+
this.multisigManager = new MultisigAccountManager({
|
|
18
|
+
threshold: info.threshold,
|
|
19
|
+
ownersWithWeight: info.ownersWithWeightPK,
|
|
20
|
+
creationNonce: info.creationNonce,
|
|
21
|
+
});
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
static async new(globals: MSafeGlobals, address: string) {
|
|
@@ -137,7 +141,7 @@ export class MSafeAccount {
|
|
|
137
141
|
sigs.push(signature);
|
|
138
142
|
}
|
|
139
143
|
}
|
|
140
|
-
const multiSignature = this.
|
|
144
|
+
const multiSignature = this.multisigManager.combinePartialSignatures(sigs);
|
|
141
145
|
return this.suiClient.executeTransactionBlock({
|
|
142
146
|
transactionBlock: HexToUint8Array(pending.payload),
|
|
143
147
|
signature: multiSignature,
|
package/src/core/MSafeClient.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { MSafeAccountInfo } from '@msafe/sui3-utils';
|
|
2
|
+
|
|
1
3
|
import { JWTToken } from '@/backend/types';
|
|
2
4
|
import { CreateHelper } from '@/core/CreateHelper';
|
|
3
5
|
import { MessageHelper } from '@/core/MessageHelper';
|
|
@@ -6,7 +8,6 @@ import { PublicKeyHelper } from '@/core/PublicKeyHelper';
|
|
|
6
8
|
import { MSafeConfigOptions, MSafeEnv } from '@/globals/const';
|
|
7
9
|
import { MSafeGlobals } from '@/globals/MSafeGlobals';
|
|
8
10
|
import { CreateMSafeAccountInfo } from '@/types/creation';
|
|
9
|
-
import { MSafeAccountInfo } from '@/types/msafe';
|
|
10
11
|
import { IWallet } from '@/types/wallet';
|
|
11
12
|
|
|
12
13
|
export class MSafeClient {
|
|
@@ -23,11 +24,6 @@ export class MSafeClient {
|
|
|
23
24
|
|
|
24
25
|
async connectWallet(input: { wallet: IWallet; jwtToken?: JWTToken }): Promise<JWTToken> {
|
|
25
26
|
this.globals.wallet = input.wallet;
|
|
26
|
-
const isValidJWT = input.jwtToken && (await this.backend.isJWTTokenValid(input.jwtToken));
|
|
27
|
-
if (isValidJWT) {
|
|
28
|
-
this.backend.setJWTToken(input.jwtToken as JWTToken);
|
|
29
|
-
return input.jwtToken as JWTToken;
|
|
30
|
-
}
|
|
31
27
|
const messageStr = MessageHelper.welcomeMessage(new Date().toUTCString());
|
|
32
28
|
const sig = await input.wallet.signPersonalMessage({
|
|
33
29
|
messageStr,
|
|
@@ -4,6 +4,7 @@ import { IBackend } from '@/backend/interface';
|
|
|
4
4
|
import { PseudoBackend } from '@/backend/PseudoBackend';
|
|
5
5
|
import { getMSafeConfig, MSafeConfig, MSafeConfigOptions, MSafeEnv } from '@/globals/const';
|
|
6
6
|
import { IWallet } from '@/types/wallet';
|
|
7
|
+
import { BackendImpl } from "@/backend/BackendImpl";
|
|
7
8
|
|
|
8
9
|
export class MSafeGlobals {
|
|
9
10
|
public readonly backend: IBackend;
|
|
@@ -23,7 +24,7 @@ export class MSafeGlobals {
|
|
|
23
24
|
static async New(env: MSafeEnv, options?: MSafeConfigOptions) {
|
|
24
25
|
const config = getMSafeConfig(env, options);
|
|
25
26
|
const suiClient = new SuiClient(config.suiClient);
|
|
26
|
-
const backend =
|
|
27
|
+
const backend = new BackendImpl(config.apiURL);
|
|
27
28
|
return new MSafeGlobals({
|
|
28
29
|
backend,
|
|
29
30
|
suiClient,
|
package/src/globals/const.ts
CHANGED
|
@@ -13,6 +13,7 @@ export interface MSafeConfig {
|
|
|
13
13
|
url: string;
|
|
14
14
|
};
|
|
15
15
|
backend: DBConfig;
|
|
16
|
+
apiURL: string;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export interface MSafeConfigOptions {
|
|
@@ -54,6 +55,9 @@ export const DEV_DATABASE_CONFIG: DBConfig = {
|
|
|
54
55
|
export const TESTNET_RPC_URL = 'https://sui-testnet.blockvision.org/v1/2Sgk89ivT64MnKdcGzjmyjY2ndD';
|
|
55
56
|
export const MAINNET_RPC_URL = 'https://sui-mainnet.blockvision.org/v1/2Sgk7NPvqkd7mESYkxF01yX15l7';
|
|
56
57
|
|
|
58
|
+
export const LOCAL_API_URL = 'http://127.0.0.1:3000';
|
|
59
|
+
export const DEV_API_URL = 'http://13.56.226.148';
|
|
60
|
+
|
|
57
61
|
export const ENV_CONFIGS = new Map<MSafeEnv, MSafeConfig>([
|
|
58
62
|
[
|
|
59
63
|
MSafeEnv.unit,
|
|
@@ -61,7 +65,8 @@ export const ENV_CONFIGS = new Map<MSafeEnv, MSafeConfig>([
|
|
|
61
65
|
suiClient: {
|
|
62
66
|
url: TESTNET_RPC_URL,
|
|
63
67
|
},
|
|
64
|
-
backend:
|
|
68
|
+
backend: LOCAL_DATABASE_CONFIG,
|
|
69
|
+
apiURL: LOCAL_API_URL,
|
|
65
70
|
},
|
|
66
71
|
],
|
|
67
72
|
[
|
|
@@ -71,6 +76,7 @@ export const ENV_CONFIGS = new Map<MSafeEnv, MSafeConfig>([
|
|
|
71
76
|
url: TESTNET_RPC_URL,
|
|
72
77
|
},
|
|
73
78
|
backend: LOCAL_DATABASE_CONFIG,
|
|
79
|
+
apiURL: LOCAL_API_URL,
|
|
74
80
|
},
|
|
75
81
|
],
|
|
76
82
|
[
|
|
@@ -80,6 +86,7 @@ export const ENV_CONFIGS = new Map<MSafeEnv, MSafeConfig>([
|
|
|
80
86
|
url: TESTNET_RPC_URL,
|
|
81
87
|
},
|
|
82
88
|
backend: DEV_DATABASE_CONFIG,
|
|
89
|
+
apiURL: DEV_API_URL,
|
|
83
90
|
},
|
|
84
91
|
],
|
|
85
92
|
]);
|
package/src/types/msafe.ts
CHANGED
|
@@ -1,25 +1,5 @@
|
|
|
1
|
-
import { PublicKey } from '@mysten/sui.js/src/cryptography';
|
|
2
|
-
|
|
3
1
|
import { TxIntention } from '@/transactions/intention';
|
|
4
2
|
|
|
5
|
-
export interface MSafeAccountInfo {
|
|
6
|
-
address: string;
|
|
7
|
-
ownersWithWeightPK: OwnerWithWeightPK[];
|
|
8
|
-
threshold: number;
|
|
9
|
-
name: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
creationNonce: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type OwnerWithWeightPK = OwnerWithWeight & {
|
|
15
|
-
publicKey: PublicKey;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export interface OwnerWithWeight {
|
|
19
|
-
address: string;
|
|
20
|
-
weight: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
3
|
export interface PendingTx {
|
|
24
4
|
digest: string;
|
|
25
5
|
payload: string;
|