@0xobelisk/client 0.0.1
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/LICENSE +202 -0
- package/README.md +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +757 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +755 -0
- package/dist/index.mjs.map +1 -0
- package/dist/libs/suiAccountManager/crypto.d.ts +1 -0
- package/dist/libs/suiAccountManager/index.d.ts +35 -0
- package/dist/libs/suiAccountManager/keypair.d.ts +21 -0
- package/dist/libs/suiAccountManager/types.d.ts +9 -0
- package/dist/libs/suiAccountManager/util.d.ts +29 -0
- package/dist/libs/suiRpcProvider/defaultChainConfigs.d.ts +8 -0
- package/dist/libs/suiRpcProvider/faucet.d.ts +8 -0
- package/dist/libs/suiRpcProvider/index.d.ts +40 -0
- package/dist/libs/suiRpcProvider/types.d.ts +14 -0
- package/dist/libs/suiTxBuilder/index.d.ts +544 -0
- package/dist/libs/suiTxBuilder/types.d.ts +12 -0
- package/dist/libs/suiTxBuilder/util.d.ts +76 -0
- package/dist/obelisk.d.ts +2857 -0
- package/dist/test/tsconfig.tsbuildinfo +1 -0
- package/dist/types/index.d.ts +11 -0
- package/package.json +152 -0
- package/src/index.ts +10 -0
- package/src/libs/suiAccountManager/crypto.ts +7 -0
- package/src/libs/suiAccountManager/index.ts +72 -0
- package/src/libs/suiAccountManager/keypair.ts +38 -0
- package/src/libs/suiAccountManager/types.ts +10 -0
- package/src/libs/suiAccountManager/util.ts +70 -0
- package/src/libs/suiRpcProvider/defaultChainConfigs.ts +30 -0
- package/src/libs/suiRpcProvider/faucet.ts +57 -0
- package/src/libs/suiRpcProvider/index.ts +114 -0
- package/src/libs/suiRpcProvider/types.ts +17 -0
- package/src/libs/suiTxBuilder/index.ts +245 -0
- package/src/libs/suiTxBuilder/types.ts +32 -0
- package/src/libs/suiTxBuilder/util.ts +84 -0
- package/src/obelisk.ts +297 -0
- package/src/types/index.ts +17 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Connection,
|
|
3
|
+
JsonRpcProvider,
|
|
4
|
+
getObjectType,
|
|
5
|
+
getObjectId,
|
|
6
|
+
getObjectFields,
|
|
7
|
+
getObjectDisplay,
|
|
8
|
+
getObjectVersion,
|
|
9
|
+
} from '@mysten/sui.js';
|
|
10
|
+
import { requestFaucet } from './faucet';
|
|
11
|
+
import { getDefaultNetworkParams } from './defaultChainConfigs';
|
|
12
|
+
import type { ObjectData, SuiRpcProviderParams } from './types';
|
|
13
|
+
|
|
14
|
+
export class SuiRpcProvider {
|
|
15
|
+
public fullnodeUrl: string;
|
|
16
|
+
public faucetUrl?: string;
|
|
17
|
+
public provider: JsonRpcProvider;
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param networkType, 'testnet' | 'mainnet' | 'devnet' | 'localnet', default is 'devnet'
|
|
21
|
+
* @param fullnodeUrl, the fullnode url, default is the preconfig fullnode url for the given network type
|
|
22
|
+
* @param faucetUrl, the faucet url, default is the preconfig faucet url for the given network type
|
|
23
|
+
*/
|
|
24
|
+
constructor({
|
|
25
|
+
fullnodeUrl,
|
|
26
|
+
faucetUrl,
|
|
27
|
+
networkType,
|
|
28
|
+
}: SuiRpcProviderParams = {}) {
|
|
29
|
+
// Get the default fullnode url and faucet url for the given network type, default is 'testnet'
|
|
30
|
+
const defaultNetworkParams = getDefaultNetworkParams(
|
|
31
|
+
networkType || 'devnet'
|
|
32
|
+
);
|
|
33
|
+
// Set fullnodeUrl and faucetUrl, if they are not provided, use the default value.
|
|
34
|
+
this.fullnodeUrl = fullnodeUrl || defaultNetworkParams.fullnode;
|
|
35
|
+
this.faucetUrl = faucetUrl || defaultNetworkParams.faucet;
|
|
36
|
+
|
|
37
|
+
// Init the provider
|
|
38
|
+
const connection = new Connection({
|
|
39
|
+
fullnode: this.fullnodeUrl,
|
|
40
|
+
faucet: this.faucetUrl,
|
|
41
|
+
});
|
|
42
|
+
this.provider = new JsonRpcProvider(connection);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Request some SUI from faucet
|
|
47
|
+
* @Returns {Promise<boolean>}, true if the request is successful, false otherwise.
|
|
48
|
+
*/
|
|
49
|
+
async requestFaucet(addr: string) {
|
|
50
|
+
return requestFaucet(addr, this.provider);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getBalance(addr: string, coinType?: string) {
|
|
54
|
+
return this.provider.getBalance({ owner: addr, coinType });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async getObjects(ids: string[]) {
|
|
58
|
+
const options = { showContent: true, showDisplay: true, showType: true };
|
|
59
|
+
const objects = await this.provider.multiGetObjects({ ids, options });
|
|
60
|
+
const parsedObjects = objects.map((object) => {
|
|
61
|
+
const objectId = getObjectId(object);
|
|
62
|
+
const objectType = getObjectType(object);
|
|
63
|
+
const objectVersion = getObjectVersion(object);
|
|
64
|
+
const objectFields = getObjectFields(object);
|
|
65
|
+
const objectDisplay = getObjectDisplay(object);
|
|
66
|
+
return {
|
|
67
|
+
objectId,
|
|
68
|
+
objectType,
|
|
69
|
+
objectVersion,
|
|
70
|
+
objectFields,
|
|
71
|
+
objectDisplay,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
return parsedObjects as ObjectData[];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @description Select coins that add up to the given amount.
|
|
79
|
+
* @param addr the address of the owner
|
|
80
|
+
* @param amount the amount that is needed for the coin
|
|
81
|
+
* @param coinType the coin type, default is '0x2::SUI::SUI'
|
|
82
|
+
*/
|
|
83
|
+
async selectCoins(
|
|
84
|
+
addr: string,
|
|
85
|
+
amount: number,
|
|
86
|
+
coinType: string = '0x2::SUI::SUI'
|
|
87
|
+
) {
|
|
88
|
+
const coins = await this.provider.getCoins({ owner: addr, coinType });
|
|
89
|
+
const selectedCoins: {
|
|
90
|
+
objectId: string;
|
|
91
|
+
digest: string;
|
|
92
|
+
version: string;
|
|
93
|
+
}[] = [];
|
|
94
|
+
let totalAmount = 0;
|
|
95
|
+
// Sort the coins by balance in descending order
|
|
96
|
+
coins.data.sort((a, b) => parseInt(b.balance) - parseInt(a.balance));
|
|
97
|
+
for (const coinData of coins.data) {
|
|
98
|
+
selectedCoins.push({
|
|
99
|
+
objectId: coinData.coinObjectId,
|
|
100
|
+
digest: coinData.digest,
|
|
101
|
+
version: coinData.version,
|
|
102
|
+
});
|
|
103
|
+
totalAmount = totalAmount + parseInt(coinData.balance);
|
|
104
|
+
if (totalAmount >= amount) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (!selectedCoins.length) {
|
|
110
|
+
throw new Error('No valid coins found for the transaction.');
|
|
111
|
+
}
|
|
112
|
+
return selectedCoins;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DisplayFieldsResponse, ObjectContentFields } from '@mysten/sui.js';
|
|
2
|
+
|
|
3
|
+
export type NetworkType = 'testnet' | 'mainnet' | 'devnet' | 'localnet';
|
|
4
|
+
|
|
5
|
+
export type ObjectData = {
|
|
6
|
+
objectId: string;
|
|
7
|
+
objectType: string;
|
|
8
|
+
objectVersion: number;
|
|
9
|
+
objectDisplay: DisplayFieldsResponse;
|
|
10
|
+
objectFields: ObjectContentFields;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type SuiRpcProviderParams = {
|
|
14
|
+
fullnodeUrl?: string;
|
|
15
|
+
faucetUrl?: string;
|
|
16
|
+
networkType?: NetworkType;
|
|
17
|
+
};
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TransactionBlock,
|
|
3
|
+
SUI_SYSTEM_STATE_OBJECT_ID,
|
|
4
|
+
TransactionExpiration,
|
|
5
|
+
SuiObjectRef,
|
|
6
|
+
SharedObjectRef,
|
|
7
|
+
JsonRpcProvider,
|
|
8
|
+
TransactionType,
|
|
9
|
+
Transactions,
|
|
10
|
+
ObjectCallArg,
|
|
11
|
+
} from '@mysten/sui.js';
|
|
12
|
+
import { convertArgs } from './util';
|
|
13
|
+
import type { SuiTxArg, SuiObjectArg, SuiVecTxArg } from './types';
|
|
14
|
+
|
|
15
|
+
export class SuiTxBlock {
|
|
16
|
+
public txBlock: TransactionBlock;
|
|
17
|
+
constructor(transaction?: TransactionBlock) {
|
|
18
|
+
this.txBlock = new TransactionBlock(transaction);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//======== override methods of TransactionBlock ============
|
|
22
|
+
|
|
23
|
+
address(value: string) {
|
|
24
|
+
return this.txBlock.pure(value, 'address');
|
|
25
|
+
}
|
|
26
|
+
pure(value: unknown, type?: string) {
|
|
27
|
+
return this.txBlock.pure(value, type);
|
|
28
|
+
}
|
|
29
|
+
object(value: string | ObjectCallArg) {
|
|
30
|
+
return this.txBlock.object(value);
|
|
31
|
+
}
|
|
32
|
+
objectRef(ref: SuiObjectRef) {
|
|
33
|
+
return this.txBlock.objectRef(ref);
|
|
34
|
+
}
|
|
35
|
+
sharedObjectRef(ref: SharedObjectRef) {
|
|
36
|
+
return this.txBlock.sharedObjectRef(ref);
|
|
37
|
+
}
|
|
38
|
+
setSender(sender: string) {
|
|
39
|
+
return this.txBlock.setSender(sender);
|
|
40
|
+
}
|
|
41
|
+
setSenderIfNotSet(sender: string) {
|
|
42
|
+
return this.txBlock.setSenderIfNotSet(sender);
|
|
43
|
+
}
|
|
44
|
+
setExpiration(expiration?: TransactionExpiration) {
|
|
45
|
+
return this.txBlock.setExpiration(expiration);
|
|
46
|
+
}
|
|
47
|
+
setGasPrice(price: number | bigint) {
|
|
48
|
+
return this.txBlock.setGasPrice(price);
|
|
49
|
+
}
|
|
50
|
+
setGasBudget(budget: number | bigint) {
|
|
51
|
+
return this.txBlock.setGasBudget(budget);
|
|
52
|
+
}
|
|
53
|
+
setGasOwner(owner: string) {
|
|
54
|
+
return this.txBlock.setGasOwner(owner);
|
|
55
|
+
}
|
|
56
|
+
setGasPayment(payments: SuiObjectRef[]) {
|
|
57
|
+
return this.txBlock.setGasPayment(payments);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
add(transaction: TransactionType) {
|
|
61
|
+
return this.txBlock.add(transaction);
|
|
62
|
+
}
|
|
63
|
+
serialize() {
|
|
64
|
+
return this.txBlock.serialize();
|
|
65
|
+
}
|
|
66
|
+
build(
|
|
67
|
+
params: {
|
|
68
|
+
provider?: JsonRpcProvider;
|
|
69
|
+
onlyTransactionKind?: boolean;
|
|
70
|
+
} = {}
|
|
71
|
+
) {
|
|
72
|
+
return this.txBlock.build(params);
|
|
73
|
+
}
|
|
74
|
+
getDigest({ provider }: { provider?: JsonRpcProvider } = {}) {
|
|
75
|
+
return this.txBlock.getDigest({ provider });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get gas() {
|
|
79
|
+
return this.txBlock.gas;
|
|
80
|
+
}
|
|
81
|
+
get blockData() {
|
|
82
|
+
return this.txBlock.blockData;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
transferObjects(objects: SuiObjectArg[], recipient: string) {
|
|
86
|
+
const tx = this.txBlock;
|
|
87
|
+
tx.transferObjects(convertArgs(this.txBlock, objects), tx.pure(recipient));
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
splitCoins(coin: SuiObjectArg, amounts: number[]) {
|
|
91
|
+
const tx = this.txBlock;
|
|
92
|
+
const coinObject = convertArgs(this.txBlock, [coin])[0];
|
|
93
|
+
const res = tx.splitCoins(
|
|
94
|
+
coinObject,
|
|
95
|
+
amounts.map((m) => tx.pure(m))
|
|
96
|
+
);
|
|
97
|
+
return amounts.map((_, i) => res[i]);
|
|
98
|
+
}
|
|
99
|
+
mergeCoins(destination: SuiObjectArg, sources: SuiObjectArg[]) {
|
|
100
|
+
const destinationObject = convertArgs(this.txBlock, [destination])[0];
|
|
101
|
+
const sourceObjects = convertArgs(this.txBlock, sources);
|
|
102
|
+
return this.txBlock.mergeCoins(destinationObject, sourceObjects);
|
|
103
|
+
}
|
|
104
|
+
publish(...args: Parameters<(typeof Transactions)['Publish']>) {
|
|
105
|
+
return this.txBlock.publish(...args);
|
|
106
|
+
}
|
|
107
|
+
upgrade(...args: Parameters<(typeof Transactions)['Upgrade']>) {
|
|
108
|
+
return this.txBlock.upgrade(...args);
|
|
109
|
+
}
|
|
110
|
+
makeMoveVec(...args: Parameters<(typeof Transactions)['MakeMoveVec']>) {
|
|
111
|
+
return this.txBlock.makeMoveVec(...args);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @description Move call
|
|
116
|
+
* @param target `${string}::${string}::${string}`, e.g. `0x3::sui_system::request_add_stake`
|
|
117
|
+
* @param args the arguments of the move call, such as `['0x1', '0x2']`
|
|
118
|
+
* @param typeArgs the type arguments of the move call, such as `['0x2::sui::SUI']`
|
|
119
|
+
*/
|
|
120
|
+
moveCall(
|
|
121
|
+
target: string,
|
|
122
|
+
args: (SuiTxArg | SuiVecTxArg)[] = [],
|
|
123
|
+
typeArgs: string[] = []
|
|
124
|
+
) {
|
|
125
|
+
// a regex for pattern `${string}::${string}::${string}`
|
|
126
|
+
const regex =
|
|
127
|
+
/(?<package>[a-zA-Z0-9]+)::(?<module>[a-zA-Z0-9_]+)::(?<function>[a-zA-Z0-9_]+)/;
|
|
128
|
+
const match = target.match(regex);
|
|
129
|
+
if (match === null)
|
|
130
|
+
throw new Error(
|
|
131
|
+
'Invalid target format. Expected `${string}::${string}::${string}`'
|
|
132
|
+
);
|
|
133
|
+
const convertedArgs = convertArgs(this.txBlock, args);
|
|
134
|
+
const tx = this.txBlock;
|
|
135
|
+
return tx.moveCall({
|
|
136
|
+
target: target as `${string}::${string}::${string}`,
|
|
137
|
+
arguments: convertedArgs,
|
|
138
|
+
typeArguments: typeArgs,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
//======== enhance methods ============
|
|
143
|
+
transferSuiToMany(recipients: string[], amounts: number[]) {
|
|
144
|
+
// require recipients.length === amounts.length
|
|
145
|
+
if (recipients.length !== amounts.length) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
'transferSuiToMany: recipients.length !== amounts.length'
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const tx = this.txBlock;
|
|
152
|
+
const coins = tx.splitCoins(
|
|
153
|
+
tx.gas,
|
|
154
|
+
amounts.map((amount) => tx.pure(amount))
|
|
155
|
+
);
|
|
156
|
+
recipients.forEach((recipient, index) => {
|
|
157
|
+
tx.transferObjects([coins[index]], tx.pure(recipient));
|
|
158
|
+
});
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
transferSui(recipient: string, amount: number) {
|
|
163
|
+
return this.transferSuiToMany([recipient], [amount]);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
takeAmountFromCoins(coins: SuiObjectArg[], amount: number) {
|
|
167
|
+
const tx = this.txBlock;
|
|
168
|
+
const coinObjects = convertArgs(this.txBlock, coins);
|
|
169
|
+
const mergedCoin = coinObjects[0];
|
|
170
|
+
if (coins.length > 1) {
|
|
171
|
+
tx.mergeCoins(mergedCoin, coinObjects.slice(1));
|
|
172
|
+
}
|
|
173
|
+
const [sendCoin] = tx.splitCoins(mergedCoin, [tx.pure(amount)]);
|
|
174
|
+
return [sendCoin, mergedCoin];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
splitSUIFromGas(amounts: number[]) {
|
|
178
|
+
const tx = this.txBlock;
|
|
179
|
+
return tx.splitCoins(
|
|
180
|
+
tx.gas,
|
|
181
|
+
amounts.map((m) => tx.pure(m))
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
splitMultiCoins(coins: SuiObjectArg[], amounts: number[]) {
|
|
186
|
+
const tx = this.txBlock;
|
|
187
|
+
const coinObjects = convertArgs(this.txBlock, coins);
|
|
188
|
+
const mergedCoin = coinObjects[0];
|
|
189
|
+
if (coins.length > 1) {
|
|
190
|
+
tx.mergeCoins(mergedCoin, coinObjects.slice(1));
|
|
191
|
+
}
|
|
192
|
+
const splitedCoins = tx.splitCoins(
|
|
193
|
+
mergedCoin,
|
|
194
|
+
amounts.map((m) => tx.pure(m))
|
|
195
|
+
);
|
|
196
|
+
return { splitedCoins, mergedCoin };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
transferCoinToMany(
|
|
200
|
+
inputCoins: SuiObjectArg[],
|
|
201
|
+
sender: string,
|
|
202
|
+
recipients: string[],
|
|
203
|
+
amounts: number[]
|
|
204
|
+
) {
|
|
205
|
+
// require recipients.length === amounts.length
|
|
206
|
+
if (recipients.length !== amounts.length) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
'transferSuiToMany: recipients.length !== amounts.length'
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
const tx = this.txBlock;
|
|
212
|
+
const { splitedCoins, mergedCoin } = this.splitMultiCoins(
|
|
213
|
+
inputCoins,
|
|
214
|
+
amounts
|
|
215
|
+
);
|
|
216
|
+
recipients.forEach((recipient, index) => {
|
|
217
|
+
tx.transferObjects([splitedCoins[index]], tx.pure(recipient));
|
|
218
|
+
});
|
|
219
|
+
tx.transferObjects([mergedCoin], tx.pure(sender));
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
transferCoin(
|
|
224
|
+
inputCoins: SuiObjectArg[],
|
|
225
|
+
sender: string,
|
|
226
|
+
recipient: string,
|
|
227
|
+
amount: number
|
|
228
|
+
) {
|
|
229
|
+
return this.transferCoinToMany(inputCoins, sender, [recipient], [amount]);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
stakeSui(amount: number, validatorAddr: string) {
|
|
233
|
+
const tx = this.txBlock;
|
|
234
|
+
const [stakeCoin] = tx.splitCoins(tx.gas, [tx.pure(amount)]);
|
|
235
|
+
tx.moveCall({
|
|
236
|
+
target: '0x3::sui_system::request_add_stake',
|
|
237
|
+
arguments: [
|
|
238
|
+
tx.object(SUI_SYSTEM_STATE_OBJECT_ID),
|
|
239
|
+
stakeCoin,
|
|
240
|
+
tx.pure(validatorAddr),
|
|
241
|
+
],
|
|
242
|
+
});
|
|
243
|
+
return tx;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SharedObjectRef,
|
|
3
|
+
SuiObjectRef,
|
|
4
|
+
TransactionArgument,
|
|
5
|
+
} from '@mysten/sui.js';
|
|
6
|
+
|
|
7
|
+
export type SuiTxArg = TransactionArgument | string | number | bigint | boolean;
|
|
8
|
+
|
|
9
|
+
export type SuiObjectArg =
|
|
10
|
+
| SharedObjectRef
|
|
11
|
+
| SuiObjectRef
|
|
12
|
+
| string
|
|
13
|
+
| TransactionArgument;
|
|
14
|
+
|
|
15
|
+
export type SuiVecTxArg =
|
|
16
|
+
| { value: SuiTxArg[]; vecType: SuiInputTypes }
|
|
17
|
+
| SuiTxArg[];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* These are the basics types that can be used in the SUI
|
|
21
|
+
*/
|
|
22
|
+
export type SuiBasicTypes =
|
|
23
|
+
| 'address'
|
|
24
|
+
| 'bool'
|
|
25
|
+
| 'u8'
|
|
26
|
+
| 'u16'
|
|
27
|
+
| 'u32'
|
|
28
|
+
| 'u64'
|
|
29
|
+
| 'u128'
|
|
30
|
+
| 'u256';
|
|
31
|
+
|
|
32
|
+
export type SuiInputTypes = 'object' | SuiBasicTypes;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeSuiObjectId,
|
|
3
|
+
TransactionArgument,
|
|
4
|
+
TransactionBlock,
|
|
5
|
+
} from '@mysten/sui.js';
|
|
6
|
+
import { SuiTxArg, SuiInputTypes } from './types';
|
|
7
|
+
|
|
8
|
+
export const getDefaultSuiInputType = (value: any): SuiInputTypes => {
|
|
9
|
+
if (typeof value === 'string' && value.startsWith('0x')) {
|
|
10
|
+
return 'object';
|
|
11
|
+
} else if (typeof value === 'number' || typeof value === 'bigint') {
|
|
12
|
+
return 'u64';
|
|
13
|
+
} else if (typeof value === 'boolean') {
|
|
14
|
+
return 'bool';
|
|
15
|
+
} else {
|
|
16
|
+
return 'object';
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Since we know the elements in the array are the same type
|
|
22
|
+
* If type is not provided, we will try to infer the type from the first element
|
|
23
|
+
* By default,
|
|
24
|
+
*
|
|
25
|
+
* string starting with `0x` =====> object id
|
|
26
|
+
* number, bigint ====> u64
|
|
27
|
+
* boolean =====> bool
|
|
28
|
+
*
|
|
29
|
+
*
|
|
30
|
+
* If type is provided, we will use the type to convert the array
|
|
31
|
+
* @param args
|
|
32
|
+
* @param type 'address' | 'bool' | 'u8' | 'u16' | 'u32' | 'u64' | 'u128' | 'u256' | 'object'
|
|
33
|
+
*/
|
|
34
|
+
export function makeVecParam(
|
|
35
|
+
txBlock: TransactionBlock,
|
|
36
|
+
args: SuiTxArg[],
|
|
37
|
+
type?: SuiInputTypes
|
|
38
|
+
) {
|
|
39
|
+
if (args.length === 0)
|
|
40
|
+
throw new Error('Transaction builder error: Empty array is not allowed');
|
|
41
|
+
const defaultSuiType = getDefaultSuiInputType(args[0]);
|
|
42
|
+
if (type === 'object' || (!type && defaultSuiType === 'object')) {
|
|
43
|
+
const objects = args.map((arg) =>
|
|
44
|
+
typeof arg === 'string'
|
|
45
|
+
? txBlock.object(normalizeSuiObjectId(arg))
|
|
46
|
+
: (arg as any)
|
|
47
|
+
);
|
|
48
|
+
return txBlock.makeMoveVec({ objects });
|
|
49
|
+
} else {
|
|
50
|
+
const vecType = type || defaultSuiType;
|
|
51
|
+
return txBlock.pure(args, `vector<${vecType}>`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isMoveVecArg(arg: any) {
|
|
56
|
+
const isFullMoveVecArg =
|
|
57
|
+
arg && arg.value && Array.isArray(arg.value) && arg.vecType;
|
|
58
|
+
const isSimpleMoveVecArg = Array.isArray(arg);
|
|
59
|
+
return isFullMoveVecArg || isSimpleMoveVecArg;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function convertArgs(
|
|
63
|
+
txBlock: TransactionBlock,
|
|
64
|
+
args: any[]
|
|
65
|
+
): TransactionArgument[] {
|
|
66
|
+
return args.map((arg) => {
|
|
67
|
+
if (typeof arg === 'string' && arg.startsWith('0x')) {
|
|
68
|
+
// We always treat string starting with `0x` as object id
|
|
69
|
+
return txBlock.object(normalizeSuiObjectId(arg));
|
|
70
|
+
} else if (isMoveVecArg(arg)) {
|
|
71
|
+
// if it's an array arg, we will convert it to move vec
|
|
72
|
+
const vecType = arg.vecType || undefined;
|
|
73
|
+
return vecType
|
|
74
|
+
? makeVecParam(txBlock, arg.value, vecType)
|
|
75
|
+
: makeVecParam(txBlock, arg);
|
|
76
|
+
} else if (typeof arg !== 'object') {
|
|
77
|
+
// Other basic types such as string, number, boolean are converted to pure value
|
|
78
|
+
return txBlock.pure(arg);
|
|
79
|
+
} else {
|
|
80
|
+
// We do nothing, because it's most likely already a move value
|
|
81
|
+
return arg;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|