@msafe/sui3-sdk 0.0.89 → 1.0.4

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/src/utils/sui.ts CHANGED
@@ -1,21 +1,64 @@
1
1
  import { PublicKeySerde } from '@msafe/sui3-utils';
2
- import { SuiClient, PaginatedTransactionResponse, PaginatedCoins, CoinStruct } from '@mysten/sui.js/client';
3
- import { parseSerializedSignature, PublicKey, SerializedSignature } from '@mysten/sui.js/cryptography';
4
- import { MultiSigPublicKey } from '@mysten/sui.js/multisig';
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
- export async function getPublicKeyFromChain(suiClient: SuiClient, address: string): Promise<PublicKey | undefined> {
11
- let txs: PaginatedTransactionResponse;
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
- txs = await suiClient.queryTransactionBlocks({
14
- // Disable naming rule since the variable is defined by Mysten
15
- filter: { FromAddress: address },
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
- if (txs.data.length === 0 || !txs.data[0].transaction?.txSignatures) {
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: SerializedSignature, targetAddress: string) {
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: SuiClient; owner: string; coinType: string | undefined }) {
119
+ export async function getAllCoins(input: { suiClient: SuiGrpcClient; owner: string; coinType: string | undefined }) {
70
120
  let hasNext = true;
71
- let cursor: string | undefined | null;
72
- const res: CoinStruct[] = [];
121
+ let cursor: string | null | undefined;
122
+ const res: SuiClientTypes.Coin[] = [];
73
123
  while (hasNext) {
74
- const currentPage: PaginatedCoins = await input.suiClient.getCoins({
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.data);
129
+ res.push(...currentPage.objects);
80
130
  hasNext = currentPage.hasNextPage;
81
- cursor = currentPage.nextCursor;
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": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
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. */