@msafe/sui3-sdk 0.0.90 → 1.0.6
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 +240 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -41
- package/dist/index.d.ts +76 -41
- package/dist/index.js +240 -105
- package/dist/index.js.map +1 -1
- package/package.json +33 -19
- package/src/backend/BackendImpl.ts +3 -3
- package/src/backend/interface.ts +2 -2
- package/src/core/CreateHelper.ts +6 -6
- package/src/core/MSafeAccount.ts +76 -66
- package/src/core/PublicKeyHelper.ts +2 -2
- package/src/globals/MSafeGlobals.ts +20 -7
- package/src/globals/const.ts +21 -5
- package/src/simulate/simulator.ts +60 -17
- package/src/types/assets.ts +3 -1
- package/src/types/msafe.ts +15 -7
- package/src/types/wallet.ts +7 -12
- package/src/utils/coin.ts +20 -7
- package/src/utils/crypto.ts +8 -13
- package/src/utils/format.ts +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/iter/object.ts +56 -43
- package/src/utils/sui.ts +71 -21
- package/src/utils/transaction.ts +12 -0
- package/tsconfig.json +1 -1
package/src/utils/coin.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { normalizeStructTag } from '@mysten/sui
|
|
1
|
+
import type { SuiGrpcClient } from '@mysten/sui/grpc';
|
|
2
|
+
import { normalizeStructTag } from '@mysten/sui/utils';
|
|
3
|
+
|
|
4
|
+
import type { CoinMetadata } from '@/types/assets';
|
|
3
5
|
|
|
4
6
|
// CoinHelper is the coin helper to query for coin metadata.
|
|
5
7
|
export class CoinHelper {
|
|
6
|
-
private _client:
|
|
8
|
+
private _client: SuiGrpcClient;
|
|
7
9
|
|
|
8
10
|
private _coinMetaReg: Map<string, CoinMetadata>;
|
|
9
11
|
|
|
10
|
-
constructor(client:
|
|
12
|
+
constructor(client: SuiGrpcClient) {
|
|
11
13
|
this._client = client;
|
|
12
14
|
this._coinMetaReg = new Map();
|
|
13
15
|
}
|
|
@@ -26,7 +28,7 @@ export class CoinHelper {
|
|
|
26
28
|
|
|
27
29
|
private async queryCoinMeta(coinType: string): Promise<CoinMetadata | undefined> {
|
|
28
30
|
const res = await this._client.getCoinMetadata({ coinType });
|
|
29
|
-
return res
|
|
31
|
+
return res.coinMetadata ?? undefined;
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -48,14 +50,25 @@ export class Coin {
|
|
|
48
50
|
return res || null;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
static getBalance(data:
|
|
53
|
+
static getBalance(data: {
|
|
54
|
+
type?: string | null;
|
|
55
|
+
json?: Record<string, unknown> | null;
|
|
56
|
+
content?: { dataType?: string; fields?: { balance?: string } };
|
|
57
|
+
}): bigint | undefined {
|
|
52
58
|
if (!Coin.isCoin(data.type)) {
|
|
53
59
|
return undefined;
|
|
54
60
|
}
|
|
61
|
+
if (data.json && typeof data.json === 'object' && 'balance' in data.json) {
|
|
62
|
+
const { balance } = data.json as { balance?: string };
|
|
63
|
+
if (balance === undefined) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
return BigInt(balance);
|
|
67
|
+
}
|
|
55
68
|
if (data.content?.dataType !== 'moveObject') {
|
|
56
69
|
return undefined;
|
|
57
70
|
}
|
|
58
|
-
const { balance } = data.content?.fields as
|
|
71
|
+
const { balance } = data.content?.fields as { balance?: string };
|
|
59
72
|
if (balance === undefined) {
|
|
60
73
|
return undefined;
|
|
61
74
|
}
|
package/src/utils/crypto.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { verifyPersonalMessage, verifyTransactionBlock } from '@mysten/sui.js/verify';
|
|
1
|
+
import { verifyPersonalMessageSignature, verifyTransactionSignature } from '@mysten/sui/verify';
|
|
3
2
|
|
|
4
3
|
import { stringToBuffer } from '@/utils/buffer';
|
|
5
4
|
import { Formatter } from '@/utils/format';
|
|
@@ -8,15 +7,15 @@ export class SignatureVerifier {
|
|
|
8
7
|
static async getPublicKeyFromSignature(input: {
|
|
9
8
|
message: Uint8Array;
|
|
10
9
|
messageType: 'TransactionBlock' | 'Personal';
|
|
11
|
-
signature:
|
|
10
|
+
signature: string;
|
|
12
11
|
}) {
|
|
13
12
|
if (input.messageType === 'TransactionBlock') {
|
|
14
|
-
return
|
|
13
|
+
return verifyTransactionSignature(input.message, input.signature);
|
|
15
14
|
}
|
|
16
|
-
return
|
|
15
|
+
return verifyPersonalMessageSignature(input.message, input.signature);
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
static async getPublicKeyFromPersonalSignature(input: { messageStr: string; signature:
|
|
18
|
+
static async getPublicKeyFromPersonalSignature(input: { messageStr: string; signature: string }) {
|
|
20
19
|
const message = stringToBuffer(input.messageStr);
|
|
21
20
|
return this.getPublicKeyFromSignature({
|
|
22
21
|
message,
|
|
@@ -28,18 +27,14 @@ export class SignatureVerifier {
|
|
|
28
27
|
static async verifySignature(input: {
|
|
29
28
|
message: Uint8Array;
|
|
30
29
|
messageType: 'TransactionBlock' | 'Personal';
|
|
31
|
-
signature:
|
|
30
|
+
signature: string;
|
|
32
31
|
targetAddress: string;
|
|
33
32
|
}) {
|
|
34
33
|
const publicKey = await SignatureVerifier.getPublicKeyFromSignature(input);
|
|
35
34
|
return Formatter.isSuiAddressEqual(publicKey.toSuiAddress(), input.targetAddress);
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
static async verifyPersonalSignature(input: {
|
|
39
|
-
messageStr: string;
|
|
40
|
-
signature: SerializedSignature;
|
|
41
|
-
targetAddress: string;
|
|
42
|
-
}) {
|
|
37
|
+
static async verifyPersonalSignature(input: { messageStr: string; signature: string; targetAddress: string }) {
|
|
43
38
|
const message = stringToBuffer(input.messageStr);
|
|
44
39
|
return this.verifySignature({
|
|
45
40
|
message,
|
|
@@ -51,7 +46,7 @@ export class SignatureVerifier {
|
|
|
51
46
|
|
|
52
47
|
static async verifyTransactionSignature(input: {
|
|
53
48
|
payload: Uint8Array;
|
|
54
|
-
signature:
|
|
49
|
+
signature: string;
|
|
55
50
|
targetAddress: string;
|
|
56
51
|
}): Promise<boolean> {
|
|
57
52
|
return this.verifySignature({
|
package/src/utils/format.ts
CHANGED
package/src/utils/index.ts
CHANGED
package/src/utils/iter/object.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SuiClientTypes } from '@mysten/sui/client';
|
|
2
|
+
import type { SuiGrpcClient } from '@mysten/sui/grpc';
|
|
2
3
|
|
|
3
4
|
import { EntryIterator, getAllFromIterator, REQUEST_PAGE_SIZE, SuiIterator } from './iterator';
|
|
4
5
|
import { PagedData, Requester } from './requester';
|
|
5
6
|
|
|
6
7
|
// TODO: setup testnet faucet and test this file
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/** Owned object row with Move JSON content (for helpers like Coin.getBalance). */
|
|
10
|
+
export type OwnedObjectData = SuiClientTypes.Object<{ json: true }>;
|
|
11
|
+
|
|
12
|
+
export type ObjectFilter = (obj: OwnedObjectData) => boolean;
|
|
9
13
|
|
|
10
14
|
// OidIter is the iterator to give the list of object ids
|
|
11
15
|
export type OidIter = SuiIterator<string>;
|
|
@@ -13,20 +17,27 @@ export type OidIter = SuiIterator<string>;
|
|
|
13
17
|
export interface BatchObjectOptions {
|
|
14
18
|
filter?: ObjectFilter;
|
|
15
19
|
pageSize?: number;
|
|
16
|
-
|
|
20
|
+
/** Extra fields to request from the node; defaults include Move JSON for struct fields. */
|
|
21
|
+
objectInclude?: SuiClientTypes.ObjectInclude;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const defaultObjectInclude: SuiClientTypes.ObjectInclude = { json: true };
|
|
25
|
+
|
|
26
|
+
function mergeInclude(options?: BatchObjectOptions): SuiClientTypes.ObjectInclude {
|
|
27
|
+
return { ...defaultObjectInclude, ...options?.objectInclude };
|
|
17
28
|
}
|
|
18
29
|
|
|
19
30
|
// getObjectsById get the list of objects by id.
|
|
20
31
|
// Compared with the multiGetObject method defined by SUI, this method will do the pagination
|
|
21
32
|
// for get object requests.
|
|
22
33
|
export async function getObjectsById(
|
|
23
|
-
provider:
|
|
34
|
+
provider: SuiGrpcClient,
|
|
24
35
|
ids: string[],
|
|
25
36
|
options?: BatchObjectOptions,
|
|
26
|
-
): Promise<(
|
|
37
|
+
): Promise<(OwnedObjectData | undefined)[]> {
|
|
27
38
|
const oidIter = new ListOidIterator(ids);
|
|
28
39
|
const iter = new ObjectBatchIterator(provider, oidIter, options);
|
|
29
|
-
return (await getAllFromIterator(iter)) as (
|
|
40
|
+
return (await getAllFromIterator(iter)) as (OwnedObjectData | undefined)[];
|
|
30
41
|
}
|
|
31
42
|
|
|
32
43
|
// ListOidIterator is the iterator that iterate through a list of ids.
|
|
@@ -53,9 +64,9 @@ export class ListOidIterator implements OidIter {
|
|
|
53
64
|
}
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
export class ObjectBatchIterator extends EntryIterator<
|
|
67
|
+
export class ObjectBatchIterator extends EntryIterator<OwnedObjectData> {
|
|
57
68
|
constructor(
|
|
58
|
-
public readonly provider:
|
|
69
|
+
public readonly provider: SuiGrpcClient,
|
|
59
70
|
public readonly idIter: OidIter,
|
|
60
71
|
public readonly options?: BatchObjectOptions,
|
|
61
72
|
) {
|
|
@@ -64,27 +75,24 @@ export class ObjectBatchIterator extends EntryIterator<SuiObjectData> {
|
|
|
64
75
|
}
|
|
65
76
|
|
|
66
77
|
// TODO: Test with customize objects
|
|
67
|
-
export class ObjectBatchRequester implements Requester<
|
|
78
|
+
export class ObjectBatchRequester implements Requester<OwnedObjectData> {
|
|
68
79
|
filter: ObjectFilter | undefined;
|
|
69
80
|
|
|
70
81
|
pageSize: number;
|
|
71
82
|
|
|
72
|
-
|
|
83
|
+
objectInclude: SuiClientTypes.ObjectInclude;
|
|
73
84
|
|
|
74
85
|
constructor(
|
|
75
|
-
public readonly provider:
|
|
86
|
+
public readonly provider: SuiGrpcClient,
|
|
76
87
|
public readonly stringIter: OidIter,
|
|
77
88
|
public options?: BatchObjectOptions,
|
|
78
89
|
) {
|
|
79
90
|
this.filter = options?.filter;
|
|
80
91
|
this.pageSize = options?.pageSize || REQUEST_PAGE_SIZE;
|
|
81
|
-
this.
|
|
82
|
-
showType: true,
|
|
83
|
-
showContent: true,
|
|
84
|
-
};
|
|
92
|
+
this.objectInclude = mergeInclude(options);
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
async doNextRequest(): Promise<PagedData<
|
|
95
|
+
async doNextRequest(): Promise<PagedData<OwnedObjectData>> {
|
|
88
96
|
const requestPage: string[] = [];
|
|
89
97
|
while (requestPage.length < this.pageSize) {
|
|
90
98
|
const hasNext = await this.stringIter.hasNext();
|
|
@@ -96,36 +104,44 @@ export class ObjectBatchRequester implements Requester<SuiObjectData> {
|
|
|
96
104
|
requestPage.push(objId);
|
|
97
105
|
}
|
|
98
106
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
const { objects } = await this.provider.getObjects({
|
|
108
|
+
objectIds: requestPage,
|
|
109
|
+
include: this.objectInclude,
|
|
102
110
|
});
|
|
103
|
-
|
|
111
|
+
const rows: OwnedObjectData[] = [];
|
|
112
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
113
|
+
for (const entry of objects) {
|
|
114
|
+
if (entry instanceof Error) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
rows.push(entry as OwnedObjectData);
|
|
118
|
+
}
|
|
119
|
+
let filtered: OwnedObjectData[];
|
|
104
120
|
if (this.filter) {
|
|
105
121
|
const { filter } = this;
|
|
106
|
-
filtered =
|
|
122
|
+
filtered = rows.filter((r) => filter(r));
|
|
107
123
|
} else {
|
|
108
|
-
filtered =
|
|
124
|
+
filtered = rows;
|
|
109
125
|
}
|
|
110
126
|
return {
|
|
111
|
-
data: filtered
|
|
127
|
+
data: filtered,
|
|
112
128
|
hasNext: await this.stringIter.hasNext(),
|
|
113
129
|
};
|
|
114
130
|
}
|
|
115
131
|
}
|
|
116
132
|
|
|
117
133
|
export async function getAllOwnedObjects(
|
|
118
|
-
provider:
|
|
134
|
+
provider: SuiGrpcClient,
|
|
119
135
|
owner: string,
|
|
120
136
|
options?: BatchObjectOptions,
|
|
121
|
-
): Promise<
|
|
137
|
+
): Promise<OwnedObjectData[]> {
|
|
122
138
|
const iter = new OwnedObjectIterator(provider, owner, options);
|
|
123
|
-
return (await getAllFromIterator(iter)) as
|
|
139
|
+
return (await getAllFromIterator(iter)) as OwnedObjectData[];
|
|
124
140
|
}
|
|
125
141
|
|
|
126
|
-
export class OwnedObjectIterator extends EntryIterator<
|
|
142
|
+
export class OwnedObjectIterator extends EntryIterator<OwnedObjectData> implements SuiIterator<OwnedObjectData> {
|
|
127
143
|
constructor(
|
|
128
|
-
public readonly provider:
|
|
144
|
+
public readonly provider: SuiGrpcClient,
|
|
129
145
|
public readonly owner: string,
|
|
130
146
|
public readonly options?: BatchObjectOptions,
|
|
131
147
|
) {
|
|
@@ -133,46 +149,43 @@ export class OwnedObjectIterator extends EntryIterator<SuiObjectData> implements
|
|
|
133
149
|
}
|
|
134
150
|
}
|
|
135
151
|
|
|
136
|
-
export class OwnedObjectRequester implements Requester<
|
|
152
|
+
export class OwnedObjectRequester implements Requester<OwnedObjectData> {
|
|
137
153
|
nextCursor: string | null;
|
|
138
154
|
|
|
139
155
|
public filter: ObjectFilter | undefined;
|
|
140
156
|
|
|
141
157
|
public pageSize: number;
|
|
142
158
|
|
|
143
|
-
public
|
|
159
|
+
public objectInclude: SuiClientTypes.ObjectInclude;
|
|
144
160
|
|
|
145
161
|
constructor(
|
|
146
|
-
public readonly provider:
|
|
162
|
+
public readonly provider: SuiGrpcClient,
|
|
147
163
|
public readonly owner: string,
|
|
148
164
|
public readonly options?: BatchObjectOptions,
|
|
149
165
|
) {
|
|
150
166
|
this.nextCursor = null;
|
|
151
167
|
this.filter = options?.filter;
|
|
152
168
|
this.pageSize = options?.pageSize || REQUEST_PAGE_SIZE;
|
|
153
|
-
this.
|
|
154
|
-
showType: true,
|
|
155
|
-
showContent: true,
|
|
156
|
-
};
|
|
169
|
+
this.objectInclude = mergeInclude(options);
|
|
157
170
|
}
|
|
158
171
|
|
|
159
|
-
async doNextRequest(): Promise<PagedData<
|
|
160
|
-
const res = await this.provider.
|
|
172
|
+
async doNextRequest(): Promise<PagedData<OwnedObjectData>> {
|
|
173
|
+
const res = await this.provider.listOwnedObjects({
|
|
161
174
|
owner: this.owner,
|
|
162
|
-
|
|
175
|
+
include: this.objectInclude,
|
|
163
176
|
cursor: this.nextCursor,
|
|
164
177
|
limit: this.pageSize,
|
|
165
178
|
});
|
|
166
|
-
this.nextCursor = res.
|
|
167
|
-
let filtered:
|
|
179
|
+
this.nextCursor = res.cursor;
|
|
180
|
+
let filtered: OwnedObjectData[];
|
|
168
181
|
if (this.filter) {
|
|
169
182
|
const { filter } = this;
|
|
170
|
-
filtered = res.
|
|
183
|
+
filtered = res.objects.filter((obj) => filter(obj as OwnedObjectData));
|
|
171
184
|
} else {
|
|
172
|
-
filtered = res.
|
|
185
|
+
filtered = res.objects as OwnedObjectData[];
|
|
173
186
|
}
|
|
174
187
|
return {
|
|
175
|
-
data: filtered
|
|
188
|
+
data: filtered,
|
|
176
189
|
hasNext: res.hasNextPage,
|
|
177
190
|
};
|
|
178
191
|
}
|
package/src/utils/sui.ts
CHANGED
|
@@ -1,21 +1,64 @@
|
|
|
1
1
|
import { PublicKeySerde } from '@msafe/sui3-utils';
|
|
2
|
-
import {
|
|
3
|
-
import { parseSerializedSignature, PublicKey
|
|
4
|
-
import {
|
|
2
|
+
import type { SuiClientTypes } from '@mysten/sui/client';
|
|
3
|
+
import { parseSerializedSignature, type PublicKey } from '@mysten/sui/cryptography';
|
|
4
|
+
import { SuiGraphQLClient } from '@mysten/sui/graphql';
|
|
5
|
+
import type { SuiGrpcClient } from '@mysten/sui/grpc';
|
|
6
|
+
import { MultiSigPublicKey } from '@mysten/sui/multisig';
|
|
5
7
|
|
|
6
8
|
import { Formatter } from '@/utils/format';
|
|
7
9
|
|
|
8
10
|
export const SUI_COIN = '0x2::sui::SUI';
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
const GRAPHQL_URL_BY_NETWORK: Record<string, string> = {
|
|
13
|
+
mainnet: 'https://sui-mainnet.mystenlabs.com/graphql',
|
|
14
|
+
testnet: 'https://sui-testnet.mystenlabs.com/graphql',
|
|
15
|
+
devnet: 'https://sui-devnet.mystenlabs.com/graphql',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function graphqlClientForGrpc(suiClient: SuiGrpcClient) {
|
|
19
|
+
const url = GRAPHQL_URL_BY_NETWORK[suiClient.network] ?? GRAPHQL_URL_BY_NETWORK.testnet;
|
|
20
|
+
return new SuiGraphQLClient({ url, network: suiClient.network });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function collectSignatureStrings(value: unknown): string[] {
|
|
24
|
+
if (typeof value === 'string') {
|
|
25
|
+
return [value];
|
|
26
|
+
}
|
|
27
|
+
if (!value || typeof value !== 'object') {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
if ('base64' in value && typeof (value as { base64: unknown }).base64 === 'string') {
|
|
31
|
+
return [(value as { base64: string }).base64];
|
|
32
|
+
}
|
|
33
|
+
if ('scheme' in value && 'base64' in value) {
|
|
34
|
+
const b64 = (value as { base64?: unknown }).base64;
|
|
35
|
+
return typeof b64 === 'string' ? [b64] : [];
|
|
36
|
+
}
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const TX_SIG_QUERY = `
|
|
41
|
+
query PublicKeyTxSigs($sender: SuiAddress!, $first: Int!) {
|
|
42
|
+
transactions(first: $first, filter: { sentAddress: $sender }) {
|
|
43
|
+
nodes {
|
|
44
|
+
signatures
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
export async function getPublicKeyFromChain(suiClient: SuiGrpcClient, address: string): Promise<PublicKey | undefined> {
|
|
51
|
+
const graphql = graphqlClientForGrpc(suiClient);
|
|
52
|
+
let txs: { transactions?: { nodes?: unknown[] } };
|
|
12
53
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
options: { showInput: true },
|
|
17
|
-
limit: 2,
|
|
54
|
+
const res = await graphql.query({
|
|
55
|
+
query: TX_SIG_QUERY,
|
|
56
|
+
variables: { sender: address, first: 2 },
|
|
18
57
|
});
|
|
58
|
+
if (res.errors?.length) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
txs = (res.data ?? {}) as { transactions?: { nodes?: unknown[] } };
|
|
19
62
|
} catch (e) {
|
|
20
63
|
// Currently when there is no history transaction, will report an error:
|
|
21
64
|
// Error: byte deserialization failed, cause by: Odd number of digits
|
|
@@ -23,11 +66,18 @@ export async function getPublicKeyFromChain(suiClient: SuiClient, address: strin
|
|
|
23
66
|
return undefined;
|
|
24
67
|
}
|
|
25
68
|
|
|
26
|
-
|
|
69
|
+
const nodes = txs.transactions?.nodes ?? [];
|
|
70
|
+
if (nodes.length === 0) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const first = nodes[0] as { signatures?: unknown };
|
|
75
|
+
const rawSigs = first.signatures;
|
|
76
|
+
const signatures: string[] = Array.isArray(rawSigs) ? rawSigs.flatMap((item) => collectSignatureStrings(item)) : [];
|
|
77
|
+
|
|
78
|
+
if (signatures.length === 0) {
|
|
27
79
|
return undefined;
|
|
28
80
|
}
|
|
29
|
-
const tx = txs.data[0];
|
|
30
|
-
const signatures = tx.transaction?.txSignatures as string[];
|
|
31
81
|
|
|
32
82
|
for (let i = 0; i !== signatures.length; i++) {
|
|
33
83
|
const serializedSig = signatures[i];
|
|
@@ -40,7 +90,7 @@ export async function getPublicKeyFromChain(suiClient: SuiClient, address: strin
|
|
|
40
90
|
return undefined;
|
|
41
91
|
}
|
|
42
92
|
|
|
43
|
-
function getAddressFromSignatures(serializedSig:
|
|
93
|
+
function getAddressFromSignatures(serializedSig: string, targetAddress: string) {
|
|
44
94
|
const decoded = parseSerializedSignature(serializedSig);
|
|
45
95
|
switch (decoded.signatureScheme) {
|
|
46
96
|
case 'MultiSig': {
|
|
@@ -56,7 +106,7 @@ function getAddressFromSignatures(serializedSig: SerializedSignature, targetAddr
|
|
|
56
106
|
case 'Secp256r1': {
|
|
57
107
|
const pk = PublicKeySerde.de({ publicKeyEncoded: decoded.publicKey, schema: decoded.signatureScheme });
|
|
58
108
|
if (Formatter.isSuiAddressEqual(pk.toSuiAddress(), targetAddress)) {
|
|
59
|
-
return pk;
|
|
109
|
+
return pk as unknown as PublicKey;
|
|
60
110
|
}
|
|
61
111
|
return undefined;
|
|
62
112
|
}
|
|
@@ -66,19 +116,19 @@ function getAddressFromSignatures(serializedSig: SerializedSignature, targetAddr
|
|
|
66
116
|
}
|
|
67
117
|
}
|
|
68
118
|
|
|
69
|
-
export async function getAllCoins(input: { suiClient:
|
|
119
|
+
export async function getAllCoins(input: { suiClient: SuiGrpcClient; owner: string; coinType: string | undefined }) {
|
|
70
120
|
let hasNext = true;
|
|
71
|
-
let cursor: string |
|
|
72
|
-
const res:
|
|
121
|
+
let cursor: string | null | undefined;
|
|
122
|
+
const res: SuiClientTypes.Coin[] = [];
|
|
73
123
|
while (hasNext) {
|
|
74
|
-
const currentPage
|
|
124
|
+
const currentPage = await input.suiClient.listCoins({
|
|
75
125
|
owner: input.owner,
|
|
76
126
|
coinType: input.coinType,
|
|
77
127
|
cursor,
|
|
78
128
|
});
|
|
79
|
-
res.push(...currentPage.
|
|
129
|
+
res.push(...currentPage.objects);
|
|
80
130
|
hasNext = currentPage.hasNextPage;
|
|
81
|
-
cursor = currentPage.
|
|
131
|
+
cursor = currentPage.cursor;
|
|
82
132
|
}
|
|
83
133
|
return res;
|
|
84
134
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Transaction, isTransaction } from '@mysten/sui/transactions';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Normalize a transaction value to {@link Transaction} (handles plain Transaction or serialized legacy shapes).
|
|
5
|
+
*/
|
|
6
|
+
export function toSuiTransaction(txb: Transaction | unknown): Transaction {
|
|
7
|
+
if (isTransaction(txb)) {
|
|
8
|
+
return txb as Transaction;
|
|
9
|
+
}
|
|
10
|
+
const legacy = txb as { serialize: () => string };
|
|
11
|
+
return Transaction.from(legacy.serialize()) as Transaction;
|
|
12
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
|
7
7
|
"module": "ES2022", /* Specify what module code is generated. */
|
|
8
8
|
"rootDir": "./", /* Specify the root folder within your source files. */
|
|
9
|
-
"moduleResolution": "
|
|
9
|
+
"moduleResolution": "bundler", /* Resolve @mysten/sui subpath exports (ESM). */
|
|
10
10
|
"baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
|
11
11
|
"paths": { "@/*": ["./src/*"] }, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
|
12
12
|
"resolveJsonModule": true, /* Enable importing .json files. */
|